From eb37006e5331757cc4a060374161f54f2fc59baf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 22 Sep 2008 10:00:31 +0000 Subject: [#17388] snap view to main views while rotating from Roelf De Kock (kiemdoder) hold down ctrl when rotating the viewport --- source/blender/src/view.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/source/blender/src/view.c b/source/blender/src/view.c index 4c56e5ce64e..d6bc9cea311 100644 --- a/source/blender/src/view.c +++ b/source/blender/src/view.c @@ -94,6 +94,9 @@ #define TRACKBALLSIZE (1.1) #define BL_NEAR_CLIP 0.001 +#define COS45 0.70710678118654746 +#define SIN45 COS45 + /* local prototypes ----------*/ void setcameratoview3d(void); /* windows.c & toets.c */ @@ -1104,6 +1107,87 @@ void viewmove(int mode) VecAddf(G.vd->ofs, G.vd->ofs, obofs); } } + + /* check for view snap */ + if (G.qual==LR_CTRLKEY){ + int i; + float viewmat[3][3]; + + static const float thres = 0.93; //cos(20 deg); + + static float snapquats[39][6] = { + /*{q0, q1, q3, q4, view, oposite_direction}*/ + {COS45, -SIN45, 0.0, 0.0, 1, 0}, //front + {0.0, 0.0, -SIN45, -SIN45, 1, 1}, //back + {1.0, 0.0, 0.0, 0.0, 7, 0}, //top + {0.0, -1.0, 0.0, 0.0, 7, 1}, //bottom + {0.5, -0.5, -0.5, -0.5, 3, 0}, //left + {0.5, -0.5, 0.5, 0.5, 3, 1}, //right + + /* some more 45 deg snaps */ + {0.65328145027160645, -0.65328145027160645, 0.27059805393218994, 0.27059805393218994, 0, 0}, + {0.92387950420379639, 0.0, 0.0, 0.38268342614173889, 0, 0}, + {0.0, -0.92387950420379639, 0.38268342614173889, 0.0, 0, 0}, + {0.35355335474014282, -0.85355335474014282, 0.35355338454246521, 0.14644660055637360, 0, 0}, + {0.85355335474014282, -0.35355335474014282, 0.14644660055637360, 0.35355338454246521, 0, 0}, + {0.49999994039535522, -0.49999994039535522, 0.49999997019767761, 0.49999997019767761, 0, 0}, + {0.27059802412986755, -0.65328145027160645, 0.65328145027160645, 0.27059802412986755, 0, 0}, + {0.65328145027160645, -0.27059802412986755, 0.27059802412986755, 0.65328145027160645, 0, 0}, + {0.27059799432754517, -0.27059799432754517, 0.65328139066696167, 0.65328139066696167, 0, 0}, + {0.38268336653709412, 0.0, 0.0, 0.92387944459915161, 0, 0}, + {0.0, -0.38268336653709412, 0.92387944459915161, 0.0, 0, 0}, + {0.14644658565521240, -0.35355335474014282, 0.85355335474014282, 0.35355335474014282, 0, 0}, + {0.35355335474014282, -0.14644658565521240, 0.35355335474014282, 0.85355335474014282, 0, 0}, + {0.0, 0.0, 0.92387944459915161, 0.38268336653709412, 0, 0}, + {-0.0, 0.0, 0.38268336653709412, 0.92387944459915161, 0, 0}, + {-0.27059802412986755, 0.27059802412986755, 0.65328133106231689, 0.65328133106231689, 0, 0}, + {-0.38268339633941650, 0.0, 0.0, 0.92387938499450684, 0, 0}, + {0.0, 0.38268339633941650, 0.92387938499450684, 0.0, 0, 0}, + {-0.14644658565521240, 0.35355338454246521, 0.85355329513549805, 0.35355332493782043, 0, 0}, + {-0.35355338454246521, 0.14644658565521240, 0.35355332493782043, 0.85355329513549805, 0, 0}, + {-0.49999991059303284, 0.49999991059303284, 0.49999985098838806, 0.49999985098838806, 0, 0}, + {-0.27059799432754517, 0.65328145027160645, 0.65328139066696167, 0.27059799432754517, 0, 0}, + {-0.65328145027160645, 0.27059799432754517, 0.27059799432754517, 0.65328139066696167, 0, 0}, + {-0.65328133106231689, 0.65328133106231689, 0.27059793472290039, 0.27059793472290039, 0, 0}, + {-0.92387932538986206, 0.0, 0.0, 0.38268333673477173, 0, 0}, + {0.0, 0.92387932538986206, 0.38268333673477173, 0.0, 0, 0}, + {-0.35355329513549805, 0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0, 0}, + {-0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0.35355329513549805, 0, 0}, + {-0.38268330693244934, 0.92387938499450684, 0.0, 0.0, 0, 0}, + {-0.92387938499450684, 0.38268330693244934, 0.0, 0.0, 0, 0}, + {-COS45, 0.0, 0.0, SIN45, 0, 0}, + {COS45, 0.0, 0.0, SIN45, 0, 0}, + {0.0, 0.0, 0.0, 1.0, 0, 0} + }; + + QuatToMat3(G.vd->viewquat, viewmat); + + for (i = 0 ; i < 39; i++){ + float snapmat[3][3]; + float view = (int)snapquats[i][4]; + float oposite_dir = (int)snapquats[i][5]; + + QuatToMat3(snapquats[i], snapmat); + + if ((Inpf(snapmat[0], viewmat[0]) > thres) && + (Inpf(snapmat[1], viewmat[1]) > thres) && + (Inpf(snapmat[2], viewmat[2]) > thres)){ + + QUATCOPY(G.vd->viewquat, snapquats[i]); + + G.vd->view = view; + if (view){ + if (oposite_dir){ + G.vd->flag2 |= V3D_OPP_DIRECTION_NAME; + }else{ + G.vd->flag2 &= ~V3D_OPP_DIRECTION_NAME; + } + } + + break; + } + } + } } else if(mode==1) { /* translate */ if(G.vd->persp==V3D_CAMOB) { -- cgit v1.2.3 From 80f4b5b94fc0829efeda6a7788ca76b335400715 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 22 Sep 2008 10:21:57 +0000 Subject: Removing control define --- intern/elbeem/CMakeLists.txt | 2 +- intern/elbeem/SConscript | 2 +- intern/elbeem/intern/solver_class.h | 4 ---- intern/elbeem/intern/solver_control.h | 7 ------- intern/elbeem/intern/solver_init.cpp | 9 +-------- intern/elbeem/intern/solver_main.cpp | 4 ++-- intern/elbeem/intern/solver_relax.h | 15 --------------- 7 files changed, 5 insertions(+), 38 deletions(-) diff --git a/intern/elbeem/CMakeLists.txt b/intern/elbeem/CMakeLists.txt index d73d0c3e06d..03fd4a3fefc 100644 --- a/intern/elbeem/CMakeLists.txt +++ b/intern/elbeem/CMakeLists.txt @@ -28,7 +28,7 @@ SET(INC ${PNG_INC} ${ZLIB_INC} ${SDL_INC} extern) FILE(GLOB SRC intern/*.cpp) -ADD_DEFINITIONS(-DNOGUI -DELBEEM_BLENDER=1 -DLBM_INCLUDE_CONTROL=1) +ADD_DEFINITIONS(-DNOGUI -DELBEEM_BLENDER=1) IF(WINDOWS) ADD_DEFINITIONS(-DUSE_MSVC6FIXES) ENDIF(WINDOWS) diff --git a/intern/elbeem/SConscript b/intern/elbeem/SConscript index 5ee8da8a071..68892ac261c 100644 --- a/intern/elbeem/SConscript +++ b/intern/elbeem/SConscript @@ -5,7 +5,7 @@ Import('env') sources = env.Glob('intern/*.cpp') -defs = 'NOGUI ELBEEM_BLENDER=1 LBM_INCLUDE_CONTROL=1' +defs = 'NOGUI ELBEEM_BLENDER=1' if env['WITH_BF_OPENMP'] == 1: defs += ' PARALLEL' diff --git a/intern/elbeem/intern/solver_class.h b/intern/elbeem/intern/solver_class.h index 310dd50617d..acfa095e1d8 100644 --- a/intern/elbeem/intern/solver_class.h +++ b/intern/elbeem/intern/solver_class.h @@ -105,9 +105,7 @@ #endif #endif -#if LBM_INCLUDE_CONTROL==1 #include "solver_control.h" -#endif #if LBM_INCLUDE_TESTSOLVERS==1 #include "solver_test.h" @@ -501,13 +499,11 @@ class LbmFsgrSolver : LbmFloat& debRAC(LbmFloat* s,int l); # endif // FSGR_STRICT_DEBUG==1 -# if LBM_INCLUDE_CONTROL==1 LbmControlData *mpControl; void initCpdata(); void handleCpdata(); void cpDebugDisplay(int dispset); -# endif // LBM_INCLUDE_CONTROL==1 bool mUseTestdata; # if LBM_INCLUDE_TESTSOLVERS==1 diff --git a/intern/elbeem/intern/solver_control.h b/intern/elbeem/intern/solver_control.h index 0f45d2133ff..57112b365ce 100644 --- a/intern/elbeem/intern/solver_control.h +++ b/intern/elbeem/intern/solver_control.h @@ -29,11 +29,6 @@ class ControlForces; #define FARF_SEPSWE 2 // relaxation macros for solver_relax.h -#if LBM_INCLUDE_CONTROL!=1 - -// defined in relax.h - -#else // LBM_INCLUDE_TESTSOLVERS!=1 // WARNING has to match controlparts.h #define CPF_ENTRIES 12 @@ -119,8 +114,6 @@ class ControlForces; if(mass0.) debMsgStd("LbmFsgrSolver::parseStdAttrList",DM_NOTIFY,"Used starttimeskip="<mPanic=1; } /*set flag*/ #endif // FSGR_STRICT_DEBUG==1 - -// #if LBM_INCLUDE_TESTSOLVERS!=1 -#if LBM_INCLUDE_CONTROL!=1 - -#define PRECOLLIDE_MODS(rho,ux,uy,uz, grav) \ - ux += (grav)[0]; \ - uy += (grav)[1]; \ - uz += (grav)[2]; - -#define TEST_IF_CHECK - -#else // LBM_INCLUDE_CONTROL!=1 -// defined in solver_control.h -#endif // LBM_INCLUDE_CONTROL!=1 - /****************************************************************************** * normal relaxation -- cgit v1.2.3 From 6e3bdacc11fc39b983420ae9d38e8b465d1cffe9 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 22 Sep 2008 10:58:50 +0000 Subject: Fixing missing function in elbeem --- intern/elbeem/extern/LBM_fluidsim.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/intern/elbeem/extern/LBM_fluidsim.h b/intern/elbeem/extern/LBM_fluidsim.h index 6e7fc86213c..dd8c63d0d39 100644 --- a/intern/elbeem/extern/LBM_fluidsim.h +++ b/intern/elbeem/extern/LBM_fluidsim.h @@ -63,11 +63,6 @@ void loadFluidsimMesh(struct Object *srcob, int useRenderParams); // WARNING - implemented in intern/elbeem/blendercall.cpp int performElbeemSimulation(char *cfgfilename); -/* init axis aligned BB for mesh object */ -// implemented in source/blender/blenkernel/intern/DerivedMesh.c -void fluidsimGetAxisAlignedBB(struct Mesh *mesh, float obmat[][4], - /*RET*/ float start[3], /*RET*/ float size[3], /*RET*/ struct Mesh **bbmesh ); - #endif -- cgit v1.2.3 From 2009ef810e5317cdbbf31caa36decb17947e225f Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Mon, 22 Sep 2008 12:18:07 +0000 Subject: Bugfix #12835 Zbuffer error in render: when you render faces clipped by 'clip end' the z values could wrap around, resulting in errors. Code not nicely clamps, plus should be faster even! --- source/blender/render/intern/source/zbuf.c | 42 ++++++++++++++++++------------ 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index 76a47a11338..1726c061df1 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -377,6 +377,8 @@ static void zbuffillAc4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, if(sn1<0) sn1= 0; if(sn2>=sn1) { + int intzverg; + zverg= (double)sn1*zxd + zy0; rz= rectzofs+sn1; rm= rectmaskofs+sn1; @@ -386,22 +388,21 @@ static void zbuffillAc4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, zverg-= zspan->polygon_offset; while(x>=0) { - if( (int)zverg < *rz) { - if(!zspan->rectmask || (int)zverg > *rm) { - // int i= zvlnr & 3; + intzverg= (int)CLAMPIS(zverg, INT_MIN, INT_MAX); + + if( intzverg < *rz) { + if(!zspan->rectmask || intzverg > *rm) { apn= ap; while(apn) { - if(apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; } + if(apn->p[0]==0) {apn->obi[0]= obi; apn->p[0]= zvlnr; apn->z[0]= intzverg; apn->mask[0]= mask; break; } if(apn->p[0]==zvlnr && apn->obi[0]==obi) {apn->mask[0]|= mask; break; } - if(apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; } + if(apn->p[1]==0) {apn->obi[1]= obi; apn->p[1]= zvlnr; apn->z[1]= intzverg; apn->mask[1]= mask; break; } if(apn->p[1]==zvlnr && apn->obi[1]==obi) {apn->mask[1]|= mask; break; } - if(apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; } + if(apn->p[2]==0) {apn->obi[2]= obi; apn->p[2]= zvlnr; apn->z[2]= intzverg; apn->mask[2]= mask; break; } if(apn->p[2]==zvlnr && apn->obi[2]==obi) {apn->mask[2]|= mask; break; } - if(apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; } + if(apn->p[3]==0) {apn->obi[3]= obi; apn->p[3]= zvlnr; apn->z[3]= intzverg; apn->mask[3]= mask; break; } if(apn->p[3]==zvlnr && apn->obi[3]==obi) {apn->mask[3]|= mask; break; } - // if(apn->p[i]==0) {apn->obi[i]= obi; apn->p[i]= zvlnr; apn->z[i]= zverg; apn->mask[i]= mask; break; } - // if(apn->p[i]==zvlnr && apn->obi[i]==obi) {apn->mask[i]|= mask; break; } if(apn->next==NULL) apn->next= addpsA(zspan); apn= apn->next; } @@ -1115,6 +1116,8 @@ static void zbuffillGLinv4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v if(sn1<0) sn1= 0; if(sn2>=sn1) { + int intzverg; + zverg= (double)sn1*zxd + zy0; rz= rectzofs+sn1; rp= rectpofs+sn1; @@ -1123,10 +1126,12 @@ static void zbuffillGLinv4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v x= sn2-sn1; while(x>=0) { - if( (int)zverg > *rz || *rz==0x7FFFFFFF) { - if(!zspan->rectmask || (int)zverg > *rm) { + intzverg= (int)CLAMPIS(zverg, INT_MIN, INT_MAX); + + if( intzverg > *rz || *rz==0x7FFFFFFF) { + if(!zspan->rectmask || intzverg > *rm) { *ro= obi; - *rz= (int)zverg; + *rz= intzverg; *rp= zvlnr; } } @@ -1231,6 +1236,8 @@ static void zbuffillGL4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, if(sn1<0) sn1= 0; if(sn2>=sn1) { + int intzverg; + zverg= (double)sn1*zxd + zy0; rz= rectzofs+sn1; rp= rectpofs+sn1; @@ -1239,9 +1246,11 @@ static void zbuffillGL4(ZSpan *zspan, int obi, int zvlnr, float *v1, float *v2, x= sn2-sn1; while(x>=0) { - if((int)zverg < *rz) { - if(!zspan->rectmask || (int)zverg > *rm) { - *rz= (int)zverg; + intzverg= (int)CLAMPIS(zverg, INT_MIN, INT_MAX); + + if(intzverg < *rz) { + if(!zspan->rectmask || intzverg > *rm) { + *rz= intzverg; *rp= zvlnr; *ro= obi; } @@ -1359,7 +1368,8 @@ static void zbuffillGL_onlyZ(ZSpan *zspan, int obi, int zvlnr, float *v1, float x= sn2-sn1; while(x>=0) { - int zvergi= (int)zverg; + int zvergi= (int)CLAMPIS(zverg, INT_MIN, INT_MAX); + /* option: maintain two depth values, closest and 2nd closest */ if(zvergi < *rz) { if(rectzofs1) *rz1= *rz; -- cgit v1.2.3 From a6edcfc4ac46b8d649a73b7271ed7b238ebcb3a9 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Mon, 22 Sep 2008 12:31:27 +0000 Subject: Fluid: Remove SDL threads, also fixed the 'finished too early' problem reported once in tracker --- source/blender/src/fluidsim.c | 86 ++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 46 deletions(-) diff --git a/source/blender/src/fluidsim.c b/source/blender/src/fluidsim.c index 05e82921e92..31cc4b81d7a 100644 --- a/source/blender/src/fluidsim.c +++ b/source/blender/src/fluidsim.c @@ -55,6 +55,7 @@ #include "DNA_key_types.h" #include "BLI_blenlib.h" +#include "BLI_threads.h" #include "BLI_arithb.h" #include "MTC_matrixops.h" @@ -86,9 +87,6 @@ #include "mydevice.h" #include "blendef.h" -#include "SDL.h" -#include "SDL_thread.h" -#include "SDL_mutex.h" #include #ifdef WIN32 /* Windos */ @@ -97,12 +95,6 @@ #define snprintf _snprintf #endif #endif -// SDL redefines main for SDL_main, not needed here... -#undef main - -#ifdef __APPLE__ /* MacOS X */ -#undef main -#endif /* from header info.c */ extern int start_progress_bar(void); @@ -287,9 +279,9 @@ static void fluidsimInitMeshChannel(float **setchannel, int size, Object *obm, i /* ********************** simulation thread ************************* */ /* ******************************************************************************** */ -SDL_mutex *globalBakeLock=NULL; -int globalBakeState = 0; // 0 everything ok, -1 abort simulation, -2 sim error, 1 sim done -int globalBakeFrame = 0; +static volatile int globalBakeState = 0; // 0 everything ok, -1 abort simulation, -2 sim error, 1 sim done +static volatile int globalBakeFrame = 0; +static volatile int g_break= 0; // run simulation in seperate thread static int fluidsimSimulateThread(void *unused) { // *ptr) { @@ -297,7 +289,7 @@ static int fluidsimSimulateThread(void *unused) { // *ptr) { int ret=0; ret = elbeemSimulate(); - SDL_mutexP(globalBakeLock); + BLI_lock_thread(LOCK_CUSTOM1); if(globalBakeState==0) { if(ret==0) { // if no error, set to normal exit @@ -307,29 +299,31 @@ static int fluidsimSimulateThread(void *unused) { // *ptr) { globalBakeState = -2; } } - SDL_mutexV(globalBakeLock); - return ret; + BLI_unlock_thread(LOCK_CUSTOM1); + return NULL; } int runSimulationCallback(void *data, int status, int frame) { //elbeemSimulationSettings *settings = (elbeemSimulationSettings*)data; //printf("elbeem blender cb s%d, f%d, domainid:%d \n", status,frame, settings->domainId ); // DEBUG - - if(!globalBakeLock) return FLUIDSIM_CBRET_ABORT; + int state = 0; if(status==FLUIDSIM_CBSTATUS_NEWFRAME) { - SDL_mutexP(globalBakeLock); + BLI_lock_thread(LOCK_CUSTOM1); globalBakeFrame = frame-1; - SDL_mutexV(globalBakeLock); + BLI_unlock_thread(LOCK_CUSTOM1); } //if((frameCounter==3) && (!frameStop)) { frameStop=1; return 1; } - SDL_mutexP(globalBakeLock); - if(globalBakeState!=0) { + BLI_lock_thread(LOCK_CUSTOM1); + state = globalBakeState; + BLI_unlock_thread(LOCK_CUSTOM1); + + if(state!=0) { return FLUIDSIM_CBRET_ABORT; } - SDL_mutexV(globalBakeLock); + return FLUIDSIM_CBRET_CONTINUE; } @@ -826,9 +820,9 @@ void fluidsimBake(struct Object *ob) } if(!doExportOnly) { - SDL_Thread *simthr = NULL; + ListBase threads; - // perform simulation with El'Beem api and SDL threads + // perform simulation with El'Beem api and threads elbeemSimulationSettings fsset; elbeemResetSettings(&fsset); fsset.version = 1; @@ -850,7 +844,7 @@ void fluidsimBake(struct Object *ob) // simulate 5 frames, each 0.03 seconds, output to ./apitest_XXX.bobj.gz fsset.animStart = domainSettings->animStart; fsset.aniFrameTime = aniFrameTime; - fsset.noOfFrames = noFrames - 1; // is otherwise subtracted in parser + fsset.noOfFrames = noFrames; // is otherwise subtracted in parser strcpy(targetFile, targetDir); strcat(targetFile, suffixSurface); // defaults for compressibility and adaptive grids @@ -1000,18 +994,13 @@ void fluidsimBake(struct Object *ob) //domainSettings->type = OB_FLUIDSIM_DOMAIN; // enable for bake display again //fsDomain->fluidsimFlag = OB_FLUIDSIM_ENABLE; // disable during bake - globalBakeLock = SDL_CreateMutex(); // set to neutral, -1 means user abort, -2 means init error globalBakeState = 0; globalBakeFrame = 0; - simthr = SDL_CreateThread(fluidsimSimulateThread, targetFile); - - if(!simthr) { - snprintf(debugStrBuffer,256,"fluidsimBake::error: Unable to create thread... running without one.\n"); - elbeemDebugOut(debugStrBuffer); - set_timecursor(0); - elbeemSimulate(); - } else { + BLI_init_threads(&threads, fluidsimSimulateThread, 1); + BLI_insert_thread(&threads, targetFile); + + { int done = 0; unsigned short event=0; short val; @@ -1019,9 +1008,12 @@ void fluidsimBake(struct Object *ob) float percentdone = 0.0; int lastRedraw = -1; + g_break= 0; + G.afbreek= 0; /* blender_test_break uses this global */ + start_progress_bar(); - while(done==0) { + while(done==0) { char busy_mess[80]; waitcursor(1); @@ -1031,16 +1023,20 @@ void fluidsimBake(struct Object *ob) sprintf(busy_mess, "baking fluids %d / %d |||", globalBakeFrame, (int) noFramesf); progress_bar(percentdone, busy_mess ); - SDL_Delay(2000); // longer delay to prevent frequent redrawing - SDL_mutexP(globalBakeLock); + // longer delay to prevent frequent redrawing + PIL_sleep_ms(2000); + + BLI_lock_thread(LOCK_CUSTOM1); if(globalBakeState != 0) done = 1; // 1=ok, <0=error/abort - SDL_mutexV(globalBakeLock); + BLI_unlock_thread(LOCK_CUSTOM1); - while(qtest()) { - event = extern_qread(&val); - if(event == ESCKEY) { + if (!G.background) { + g_break= blender_test_break(); + + if(g_break) + { // abort... - SDL_mutexP(globalBakeLock); + BLI_lock_thread(LOCK_CUSTOM1); if(domainSettings) domainSettings->lastgoodframe = startFrame+globalBakeFrame; @@ -1049,7 +1045,7 @@ void fluidsimBake(struct Object *ob) globalBakeFrame = 0; globalBakeState = -1; simAborted = 1; - SDL_mutexV(globalBakeLock); + BLI_unlock_thread(LOCK_CUSTOM1); break; } } @@ -1068,11 +1064,9 @@ void fluidsimBake(struct Object *ob) screen_swapbuffers(); } // redraw } - SDL_WaitThread(simthr,NULL); end_progress_bar(); } - SDL_DestroyMutex(globalBakeLock); - globalBakeLock = NULL; + BLI_end_threads(&threads); } // El'Beem API init, thread creation // -------------------------------------------------------------------------------------------- else -- cgit v1.2.3 From c79f99224dbfd046e84cbfccc74580ed4220859b Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 22 Sep 2008 13:01:51 +0000 Subject: Bugfix #14428: Constraints lost when object made single user When there was a setup where an object was linked to more than one scene at once, and in one of those scenes some of the objects in that scene were related to it, the objects related to it were not correctly relinked to the new copy. This was due to the 2nd check for selected objects if( (base->flag & flag)==flag) meaning that only selected objects would get corrected. --- source/blender/src/editobject.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 67709357225..a52882e6003 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -4381,18 +4381,17 @@ void single_object_users(int flag) clear_sca_new_poins(); /* sensor/contr/act */ - /* duplicate */ + /* duplicate (must set newid) */ base= FIRSTBASE; while(base) { ob= base->object; - if( (base->flag & flag)==flag) { - + if( (base->flag & flag)==flag ) { if(ob->id.lib==NULL && ob->id.us>1) { - + /* base gets copy of object */ obn= copy_object(ob); - ob->id.us--; base->object= obn; + ob->id.us--; } } base= base->next; @@ -4406,20 +4405,17 @@ void single_object_users(int flag) while(base) { ob= base->object; if(ob->id.lib==NULL) { - if( (base->flag & flag)==flag) { - - relink_constraints(&base->object->constraints); - if (base->object->pose){ - bPoseChannel *chan; - for (chan = base->object->pose->chanbase.first; chan; chan=chan->next){ - relink_constraints(&chan->constraints); - } + relink_constraints(&base->object->constraints); + if (base->object->pose){ + bPoseChannel *chan; + for (chan = base->object->pose->chanbase.first; chan; chan=chan->next){ + relink_constraints(&chan->constraints); } - modifiers_foreachObjectLink(base->object, single_object_users__forwardModifierLinks, NULL); - - ID_NEW(ob->parent); - ID_NEW(ob->track); } + modifiers_foreachObjectLink(base->object, single_object_users__forwardModifierLinks, NULL); + + ID_NEW(ob->parent); + ID_NEW(ob->track); } base= base->next; } -- cgit v1.2.3 From bc151f133478dff9190fae6e63e58dc7cdbfeb75 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Mon, 22 Sep 2008 14:52:50 +0000 Subject: Bugfix: - Button for 'shadow color' was drawn over 'layer shadow' button... The shadow+spot panel was cramped... spot shadowbuffer uses all space. Moved it to the Lamp panel with label, more clear now. Panel reorg is for later :) - Small fix: Area Lamp 'gamma' slider didn't update preview. Unfortunately had to move this slider to smaller button... --- source/blender/src/buttons_shading.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index e58ef3f5b12..c70c2ed0b39 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -2672,12 +2672,6 @@ static void lamp_panel_spot(Object *ob, Lamp *la) uiDefButBitI(block, TOG, LA_LAYER_SHADOW, B_LAMPPRV,"Layer", 10,90,80,19,&la->mode, 0, 0, 0, 0, "Causes only objects on the same layer to cast shadows"); uiBlockEndAlign(block); - if(ELEM4(la->type, LA_AREA, LA_SPOT, LA_SUN, LA_LOCAL) && ((la->mode & LA_SHAD_RAY)||(la->mode & LA_SHAD_BUF))) { - uiBlockBeginAlign(block); - uiDefButF(block, COL, 0, "Shadow ", 10,90,80,19,&la->shdwr, 0, 0, 0, B_COLLAMP, "Sets the shadow color; default is black (RGB 0,0,0)"); - uiBlockEndAlign(block); - } - if(la->type==LA_SPOT) { uiBlockBeginAlign(block); uiDefButBitI(block, TOG, LA_SQUARE, B_LAMPREDRAW,"Square", 10,60,80,19,&la->mode, 0, 0, 0, 0, "Sets square spotbundles"); @@ -2995,7 +2989,16 @@ static void lamp_panel_lamp(Object *ob, Lamp *la) } else if(la->type==LA_AREA) { if(la->k==0.0) la->k= 1.0; - uiDefButF(block, NUMSLI,0,"Gamma ", 120,10,180,19,&la->k, 0.001, 2.0, 100, 0, "Set the light gamma correction value"); + uiDefButF(block, NUM,B_LAMPPRV, "Gam. ", 10,95,100,19, &la->k, 0.001, 2.0, 100, 0, "Set the light gamma correction value"); + } + uiBlockEndAlign(block); + + if(ELEM4(la->type, LA_AREA, LA_SPOT, LA_SUN, LA_LOCAL) && ((la->mode & LA_SHAD_RAY)||(la->mode & LA_SHAD_BUF))) { + + uiDefBut(block, LABEL, 0, "Shadow Color", 120, 32, 180, 20, 0, 0.0, 0.0, 0, 0, ""); + uiBlockBeginAlign(block); + uiDefButF(block, COL, 0, "Shadow ", 120,10,180,22,&la->shdwr, 0, 0, 0, B_COLLAMP, "Sets the shadow color; default is black (RGB 0,0,0)"); + } } -- cgit v1.2.3 From e4def00d5bc8c4b2947f74d2b5c3308ae07a4eee Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 22 Sep 2008 15:37:32 +0000 Subject: fix for [#15020] File browser: going back from the root of all directories introduces "../" ad libitum + harcoded path? bug was introduced when fixing BLI_cleanup_dir not to write to negative character indicies. added a BLI_parent_dir(char *path) --- source/blender/blenlib/BLI_blenlib.h | 3 ++ source/blender/blenlib/intern/util.c | 15 +++++++++ source/blender/src/editimasel.c | 13 +++++--- source/blender/src/filelist.c | 30 +----------------- source/blender/src/filesel.c | 59 +++++++++--------------------------- 5 files changed, 42 insertions(+), 78 deletions(-) diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index 6a50e2de0e5..4bbda9709d7 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -137,6 +137,9 @@ void BLI_dlist_reinit(struct DynamicList *dlist); void BLI_cleanup_file(const char *relabase, char *dir); void BLI_cleanup_dir(const char *relabase, char *dir); /* same as above but adds a trailing slash */ +/* go back one directory */ +int BLI_parent_dir(char *path); + /** * Blender's path code replacement function. * Bases @a path strings leading with "//" by the diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index 9dfe9557c1b..1630842be05 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1058,6 +1058,21 @@ void BLI_makestringcode(const char *relfile, char *file) } } +int BLI_parent_dir(char *path) +{ + char tmp[FILE_MAXDIR+FILE_MAXFILE+4]; + BLI_strncpy(tmp, path, sizeof(tmp)); + BLI_add_slash(tmp); + strcat(tmp, "../"); + BLI_cleanup_dir(NULL, tmp); + + if (!BLI_testextensie(tmp, "../")) { + BLI_strncpy(path, tmp, sizeof(tmp)); + return 1; + } else { + return 0; + } +} int BLI_convertstringframe(char *path, int frame) { diff --git a/source/blender/src/editimasel.c b/source/blender/src/editimasel.c index 97ddc2e0f1d..8335af21247 100644 --- a/source/blender/src/editimasel.c +++ b/source/blender/src/editimasel.c @@ -959,10 +959,15 @@ void winqreadimaselspace(ScrArea *sa, void *spacedata, BWinEvent *evt) { error("Path too long, cannot enter this directory"); } else { - strcat(simasel->dir, file->relname); - strcat(simasel->dir,"/"); - simasel->file[0] = '\0'; - BLI_cleanup_dir(G.sce, simasel->dir); + if (strcmp(file->relname, "..")==0) { + /* avoids /../../ */ + BLI_parent_dir(simasel->dir); + } else { + strcat(simasel->dir, file->relname); + strcat(simasel->dir,"/"); + simasel->file[0] = '\0'; + BLI_cleanup_dir(G.sce, simasel->dir); + } BIF_filelist_setdir(simasel->files, simasel->dir); BIF_filelist_free(simasel->files); simasel->active_file = -1; diff --git a/source/blender/src/filelist.c b/source/blender/src/filelist.c index 589afb7f75f..c2c0f00885f 100644 --- a/source/blender/src/filelist.c +++ b/source/blender/src/filelist.c @@ -629,35 +629,7 @@ int BIF_filelist_empty(struct FileList* filelist) void BIF_filelist_parent(struct FileList* filelist) { -#ifdef WIN32 - char c = '\\'; -#else - char c = '/'; -#endif - char *dir = filelist->dir; - size_t len = strlen(dir); - - while( (len > 0) && (dir[len-1] == c) ) - { - --len; - dir[len] = '\0'; - } - while ( (len > 0) && (dir[len-1] != c) ) - { - --len; - dir[len] = '\0'; - } - if (len == 0) - { - dir[0] = c; dir[1] = '\0'; - } -#ifdef WIN32 - strcat(filelist->dir, "\\"); -#else - strcat(filelist->dir, "/"); -#endif - - BLI_cleanup_dir(G.sce, filelist->dir); + BLI_parent_dir(filelist->dir); BLI_make_exist(filelist->dir); BIF_filelist_readdir(filelist); } diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c index cdb001d9193..22f7e577ad9 100644 --- a/source/blender/src/filesel.c +++ b/source/blender/src/filesel.c @@ -555,54 +555,18 @@ static void split_sfile(SpaceFile *sfile, char *s1) void parent(SpaceFile *sfile) { - short a; - char *dir; + char path[sizeof(sfile->dir)+4]; /* if databrowse: no parent */ if(sfile->type==FILE_MAIN && filesel_has_func(sfile)) return; - - dir= sfile->dir; + BLI_parent_dir(sfile->dir); + + if (sfile->type!=FILE_MAIN && (sfile->dir[0]=='\0')) #ifdef WIN32 - if( (a = strlen(dir)) ) { /* remove all '/' at the end */ - while(dir[a-1] == '\\') { - a--; - dir[a] = 0; - if (a<=0) break; - } - } - if( (a = strlen(dir)) ) { /* then remove all until '/' */ - while(dir[a-1] != '\\') { - a--; - dir[a] = 0; - if (a<=0) break; - } - } - if( (a = strlen(dir)) ) { - if (dir[a-1] != '\\') strcat(dir,"\\"); - } - else if(sfile->type!=FILE_MAIN) { - get_default_root(dir); - } + get_default_root(sfile->dir); #else - if( (a = strlen(dir)) ) { /* remove all '/' at the end */ - while(dir[a-1] == '/') { - a--; - dir[a] = 0; - if (a<=0) break; - } - } - if( (a = strlen(dir)) ) { /* then remove until '/' */ - while(dir[a-1] != '/') { - a--; - dir[a] = 0; - if (a<=0) break; - } - } - if ( (a = strlen(dir)) ) { - if (dir[a-1] != '/') strcat(dir,"/"); - } - else if(sfile->type!=FILE_MAIN) strcpy(dir,"/"); + strcpy(sfile->dir,"/"); #endif /* to be sure */ @@ -1914,9 +1878,14 @@ void winqreadfilespace(ScrArea *sa, void *spacedata, BWinEvent *evt) { error("Path too long, cannot enter this directory"); } else { - strcat(sfile->dir, sfile->filelist[act].relname); - strcat(sfile->dir,"/"); - BLI_cleanup_dir(G.sce, sfile->dir); + if (strcmp(sfile->filelist[act].relname, "..")==0) { + /* avoids /../../ */ + BLI_parent_dir(sfile->dir); + } else { + strcat(sfile->dir, sfile->filelist[act].relname); + strcat(sfile->dir,"/"); + BLI_cleanup_dir(G.sce, sfile->dir); + } freefilelist(sfile); sfile->ofs= 0; do_draw= 1; -- cgit v1.2.3 From 627c6178f99a125bf63e153340168d20facb946a Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Mon, 22 Sep 2008 15:38:17 +0000 Subject: Realy time for 2.5! Takes half an hour to find a nice empty spot for a button! Another attempt to locate new shadow color swatch. Now back in shadow panel, bottom. --- source/blender/src/buttons_shading.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index c70c2ed0b39..2fdd1ba2f50 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -2766,6 +2766,17 @@ static void lamp_panel_spot(Object *ob, Lamp *la) } else uiDefBut(block, LABEL,0," ", 100,180,200,19,NULL, 0, 0, 0, 0, ""); + if(ELEM4(la->type, LA_AREA, LA_SPOT, LA_SUN, LA_LOCAL) && ((la->mode & LA_SHAD_RAY)||(la->mode & LA_SHAD_BUF))) { + short yval= 10; + if(la->type == LA_SPOT && (la->mode & LA_SHAD_BUF)) + yval= -15; + if(la->type != LA_SPOT) + uiDefBut(block, LABEL, 0, "Shadow", 10,30,90,19,NULL, 0, 0, 0, 0, ""); + + uiBlockBeginAlign(block); + uiDefButF(block, COL, 0, "", 10,yval,90,19,&la->shdwr, 0, 0, 0, B_COLLAMP, "Sets the shadow color; default is black (RGB 0,0,0)"); + } + } /* yafray: adaptation of lamp_panel_spot above with yafray specific parameters */ @@ -2981,25 +2992,18 @@ static void lamp_panel_lamp(Object *ob, Lamp *la) uiBlockEndAlign(block); uiDefButF(block, COL, B_LAMPPRV, "", 120,52,180,24, &la->r, 0, 0, 0, B_COLLAMP, ""); + uiBlockEndAlign(block); - uiBlockBeginAlign(block); if (ELEM(la->type, LA_LOCAL, LA_SPOT) && (la->falloff_type == LA_FALLOFF_SLIDERS)) { + uiBlockBeginAlign(block); uiDefButF(block, NUMSLI,B_LAMPPRV,"Linear ", 120,30,180,19,&la->att1, 0.0, 1.0, 0, 0, "Set the linear distance attenuation for a Lin/Quad Weighted lamp"); uiDefButF(block, NUMSLI,B_LAMPPRV,"Quad ", 120,10,180,19,&la->att2, 0.0, 1.0, 0, 0, "Set the quadratic distance attenuation for a Lin/Quad Weighted lamp"); } else if(la->type==LA_AREA) { if(la->k==0.0) la->k= 1.0; - uiDefButF(block, NUM,B_LAMPPRV, "Gam. ", 10,95,100,19, &la->k, 0.001, 2.0, 100, 0, "Set the light gamma correction value"); + uiDefButF(block, NUMSLI,B_LAMPPRV,"Gamma ", 120,10,180,19,&la->k, 0.001, 2.0, 100, 0, "Set the light gamma correction value"); } - uiBlockEndAlign(block); - if(ELEM4(la->type, LA_AREA, LA_SPOT, LA_SUN, LA_LOCAL) && ((la->mode & LA_SHAD_RAY)||(la->mode & LA_SHAD_BUF))) { - - uiDefBut(block, LABEL, 0, "Shadow Color", 120, 32, 180, 20, 0, 0.0, 0.0, 0, 0, ""); - uiBlockBeginAlign(block); - uiDefButF(block, COL, 0, "Shadow ", 120,10,180,22,&la->shdwr, 0, 0, 0, B_COLLAMP, "Sets the shadow color; default is black (RGB 0,0,0)"); - - } } -- cgit v1.2.3 From 558d7499a65cb17332741823d46f27cf39ce2a21 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Mon, 22 Sep 2008 15:59:04 +0000 Subject: Patch #17666 by Vladimir Marek Fixes for solaris compiling --- intern/elbeem/intern/isosurface.cpp | 4 ++++ intern/elbeem/intern/mvmcoords.h | 4 ++++ intern/elbeem/intern/solver_class.h | 1 + 3 files changed, 9 insertions(+) diff --git a/intern/elbeem/intern/isosurface.cpp b/intern/elbeem/intern/isosurface.cpp index 9925565b85d..751a48cebba 100644 --- a/intern/elbeem/intern/isosurface.cpp +++ b/intern/elbeem/intern/isosurface.cpp @@ -13,6 +13,10 @@ #include #include +#ifdef sun +#include "ieeefp.h" +#endif + // just use default rounding for platforms where its not available #ifndef round #define round(x) (x) diff --git a/intern/elbeem/intern/mvmcoords.h b/intern/elbeem/intern/mvmcoords.h index 51b0958ed78..889f5058a09 100644 --- a/intern/elbeem/intern/mvmcoords.h +++ b/intern/elbeem/intern/mvmcoords.h @@ -27,6 +27,10 @@ #endif #endif +#ifdef sun +#include "ieeefp.h" +#endif + // weight and triangle index class mvmIndexWeight { public: diff --git a/intern/elbeem/intern/solver_class.h b/intern/elbeem/intern/solver_class.h index acfa095e1d8..f61ef72e8ab 100644 --- a/intern/elbeem/intern/solver_class.h +++ b/intern/elbeem/intern/solver_class.h @@ -100,6 +100,7 @@ // sirdude fix for solaris #if !defined(linux) && defined(sun) +#include "ieeefp.h" #ifndef expf #define expf(x) exp((double)(x)) #endif -- cgit v1.2.3 From b40ed96a78d787c2a7d8b231c62e2ffe33bcc74b Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Mon, 22 Sep 2008 15:59:50 +0000 Subject: Patch #17665 by Vladimir Marek Fixes for solaris compiling --- source/blender/blenloader/intern/readfile.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8d998016667..7805f98f5d1 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -37,11 +37,9 @@ #ifdef WIN32 #include "winsock2.h" #include "BLI_winstuff.h" -#ifndef INT_MAX -#include "limits.h" -#endif #endif +#include #include // for printf fopen fwrite fclose sprintf FILE #include // for getenv atoi #include // for open -- cgit v1.2.3 From 315ef8213c9b025bcebe9af4502a08e60148ce9c Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Mon, 22 Sep 2008 17:12:57 +0000 Subject: BGE patch #17483 approved: object actuator DRot reverted since Blender 246. --- source/blender/blenloader/intern/readfile.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 7805f98f5d1..f2478421737 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7766,6 +7766,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main) /* sun/sky */ if(main->versionfile < 246) { Lamp *la; + Object *ob; + bActuator *act; for(la=main->lamp.first; la; la= la->id.next) { la->sun_effect_type = 0; @@ -7780,10 +7782,22 @@ static void do_versions(FileData *fd, Library *lib, Main *main) la->atm_distance_factor = 1.0; la->sun_intensity = 1.0; } + /* dRot actuator change direction in 2.46 */ + for(ob = main->object.first; ob; ob= ob->id.next) { + for(act= ob->actuators.first; act; act= act->next) { + if (act->type == ACT_OBJECT) { + bObjectActuator *ba= act->data; + + ba->drot[0] = -ba->drot[0]; + ba->drot[1] = -ba->drot[1]; + ba->drot[2] = -ba->drot[2]; + } + } + } } // convert fluids to modifier - if(main->versionfile <= 246 && main->subversionfile < 1) + if(main->versionfile < 246 || (main->versionfile == 246 && main->subversionfile < 1)) { Object *ob; -- cgit v1.2.3 From 48c54c275b10e6cb2e26d488e26820703f0ee67b Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 22 Sep 2008 18:33:04 +0000 Subject: Further fix for #8132, mac/nvidia driver issue drawing node previews, zoom level was not correct. --- source/blender/src/drawnode.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/source/blender/src/drawnode.c b/source/blender/src/drawnode.c index 853df3bedfc..d2586c9b781 100644 --- a/source/blender/src/drawnode.c +++ b/source/blender/src/drawnode.c @@ -2468,7 +2468,16 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv) } } - glPixelZoom(xscale, yscale); +#ifdef __APPLE__ + if(is_a_really_crappy_nvidia_card()) { + float zoomx= curarea->winx/(float)(G.v2d->cur.xmax-G.v2d->cur.xmin); + float zoomy= curarea->winy/(float)(G.v2d->cur.ymax-G.v2d->cur.ymin); + glPixelZoom(zoomx*xscale, zoomy*yscale); + } + else +#endif + glPixelZoom(xscale, yscale); + glEnable(GL_BLEND); glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA ); /* premul graphics */ -- cgit v1.2.3 From 4e731c5ab5ba9e12748a5632329dcc0854def928 Mon Sep 17 00:00:00 2001 From: Diego Borghetti Date: Mon, 22 Sep 2008 19:09:46 +0000 Subject: Revert full screen, maximized and minimized code (rev 16543). Revert this because don't work "fine" with dual-monitor. The problem is not the code, this work fine, but full screen for a window manager is not both monitor (until set xinerama or whatever..). --- intern/ghost/intern/GHOST_SystemX11.cpp | 40 +--- intern/ghost/intern/GHOST_SystemX11.h | 16 +- intern/ghost/intern/GHOST_WindowX11.cpp | 374 +++++--------------------------- intern/ghost/intern/GHOST_WindowX11.h | 21 -- 4 files changed, 65 insertions(+), 386 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 047bc654559..8073756e453 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -96,25 +96,17 @@ GHOST_SystemX11( if (!m_display) return; #ifdef __sgi - m_delete_window_atom = XSGIFastInternAtom(m_display, + m_delete_window_atom + = XSGIFastInternAtom(m_display, "WM_DELETE_WINDOW", SGI_XA_WM_DELETE_WINDOW, False); #else - m_delete_window_atom = XInternAtom(m_display, "WM_DELETE_WINDOW", False); + m_delete_window_atom + = XInternAtom(m_display, "WM_DELETE_WINDOW", True); #endif m_wm_protocols= XInternAtom(m_display, "WM_PROTOCOLS", False); m_wm_take_focus= XInternAtom(m_display, "WM_TAKE_FOCUS", False); - m_wm_state= XInternAtom(m_display, "WM_STATE", False); - m_wm_change_state= XInternAtom(m_display, "WM_CHANGE_STATE", False); - m_net_state= XInternAtom(m_display, "_NET_WM_STATE", False); - m_net_max_horz= XInternAtom(m_display, - "_NET_WM_STATE_MAXIMIZED_HORZ", False); - m_net_max_vert= XInternAtom(m_display, - "_NET_WM_STATE_MAXIMIZED_VERT", False); - m_net_fullscreen= XInternAtom(m_display, - "_NET_WM_STATE_FULLSCREEN", False); - m_motif= XInternAtom(m_display, "_MOTIF_WM_HINTS", False); // compute the initial time timeval tv; @@ -522,12 +514,10 @@ GHOST_SystemX11::processEvent(XEvent *xe) GHOST_kEventNDOFButton, window, data); } - } - else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) { + } else if (((Atom)xcme.data.l[0]) == m_wm_take_focus) { /* as ICCCM say, we need reply this event * with a SetInputFocus, the data[1] have - * the valid timestamp (send by the window - * manager). + * the valid timestamp (send by the wm). */ XSetInputFocus(m_display, xcme.window, RevertToParent, xcme.data.l[1]); } else { @@ -547,24 +537,6 @@ GHOST_SystemX11::processEvent(XEvent *xe) // XCrossingEvents pointer leave enter window. break; case MapNotify: - /* - * From ICCCM: - * [ Clients can select for StructureNotify on their - * top-level windows to track transition between - * Normal and Iconic states. Receipt of a MapNotify - * event will indicate a transition to the Normal - * state, and receipt of an UnmapNotify event will - * indicate a transition to the Iconic state. ] - */ - if (window->m_post_init == True) { - /* - * Now we are sure that the window is - * mapped, so only need change the state. - */ - window->setState(window->m_post_state); - window->m_post_init= False; - } - break; case UnmapNotify: break; case MappingNotify: diff --git a/intern/ghost/intern/GHOST_SystemX11.h b/intern/ghost/intern/GHOST_SystemX11.h index 683337b47e1..576577917ba 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -215,21 +215,9 @@ public: */ virtual void putClipboard(GHOST_TInt8 *buffer, int flag) const; - /** - * Atom used for ICCCM, WM-spec and Motif. - * We only need get this atom at the start, it's relative - * to the display not the window and are public for every - * window that need it. - */ - Atom m_wm_protocols; + /* Atom used for ICCCM. */ Atom m_wm_take_focus; - Atom m_wm_state; - Atom m_wm_change_state; - Atom m_net_state; - Atom m_net_max_horz; - Atom m_net_max_vert; - Atom m_net_fullscreen; - Atom m_motif; + Atom m_wm_protocols; Atom m_delete_window_atom; private : diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 2f7aee95b82..73d61a30977 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -54,16 +54,6 @@ typedef struct { #define MWM_HINTS_DECORATIONS (1L << 1) -/* - * A client can't change the window property, that is the - * work of the window manager. We send a ClientMessage - * event to the Root window with the property - * and the Action (WM-spec define this): - */ -#define _NET_WM_STATE_REMOVE 0 -#define _NET_WM_STATE_ADD 1 -#define _NET_WM_STATE_TOGGLE 2 - /* import bpy I = bpy.data.images['blender.png'] # the 48x48 icon @@ -164,10 +154,10 @@ GHOST_WindowX11( // Set up the minimum atrributes that we require and see if // X can find us a visual matching those requirements. - Atom atoms[2]; - int natom; + int attributes[40], i = 0; - + Atom atoms[2]; + int natom; if(m_stereoVisual) attributes[i++] = GLX_STEREO; @@ -272,26 +262,46 @@ GHOST_WindowX11( // Are we in fullscreen mode - then include // some obscure blut code to remove decorations. - /* - * One of the problem with WM_spec is that can't set a property - * to a window that isn't mapped. That is why we can't "just - * call setState" here. - * - * To fix this, we first need know that the window is really - * mapped waiting for the MapNotify event. - * - * So, m_post_init indicate that we need wait for the MapNotify - * event and then set the window state to the m_post_state. - */ - if ((state != GHOST_kWindowStateNormal) && (state != GHOST_kWindowStateMinimized)) { - m_post_init = True; - m_post_state = state; - } - else { - m_post_init = False; - m_post_state = GHOST_kWindowStateNormal; - } + if (state == GHOST_kWindowStateFullScreen) { + MotifWmHints hints; + Atom atom; + + atom = XInternAtom(m_display, "_MOTIF_WM_HINTS", False); + + if (atom == None) { + GHOST_PRINT("Could not intern X atom for _MOTIF_WM_HINTS.\n"); + } else { + hints.flags = MWM_HINTS_DECORATIONS; + hints.decorations = 0; /* Absolutely no decorations. */ + // other hints.decorations make no sense + // you can't select individual decorations + + XChangeProperty(m_display, m_window, + atom, atom, 32, + PropModeReplace, (unsigned char *) &hints, 4); + } + } else if (state == GHOST_kWindowStateMaximized) { + // With this, xprop should report the following just after launch + // _NET_WM_STATE(ATOM) = _NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ + // After demaximization the right side is empty, though (maybe not the most correct then?) + Atom state, atomh, atomv; + + state = XInternAtom(m_display, "_NET_WM_STATE", False); + atomh = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_HORZ", False); + atomv = XInternAtom(m_display, "_NET_WM_STATE_MAXIMIZED_VERT", False); + if (state == None ) { + GHOST_PRINT("Atom _NET_WM_STATE requested but not avaliable nor created.\n"); + } else { + XChangeProperty(m_display, m_window, + state, XA_ATOM, 32, + PropModeAppend, (unsigned char *) &atomh, 1); + XChangeProperty(m_display, m_window, + state, XA_ATOM, 32, + PropModeAppend, (unsigned char *) &atomv, 1); + } + } + // Create some hints for the window manager on how // we want this window treated. @@ -654,298 +664,28 @@ clientToScreen( outY = ay; } -void GHOST_WindowX11::icccmSetState(int state) -{ - XEvent xev; - - if (state != IconicState) - return; - - xev.xclient.type = ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = True; - xev.xclient.display = m_display; - xev.xclient.window = m_window; - xev.xclient.format = 32; - xev.xclient.message_type = m_system->m_wm_change_state; - xev.xclient.data.l[0] = state; - XSendEvent (m_display, RootWindow(m_display, DefaultScreen(m_display)), - False, SubstructureNotifyMask | SubstructureRedirectMask, &xev); -} - -int GHOST_WindowX11::icccmGetState(void) const -{ - unsigned char *prop_ret; - unsigned long bytes_after, num_ret; - Atom type_ret; - int format_ret, st; - - prop_ret = NULL; - st = XGetWindowProperty(m_display, m_window, m_system->m_wm_state, 0, - 0x7fffffff, False, m_system->m_wm_state, &type_ret, - &format_ret, &num_ret, &bytes_after, &prop_ret); - - if ((st == Success) && (prop_ret) && (num_ret == 2)) - st = prop_ret[0]; - else - st = NormalState; - - if (prop_ret) - XFree(prop_ret); - return (st); -} - -void GHOST_WindowX11::netwmMaximized(bool set) -{ - XEvent xev; - - xev.xclient.type= ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = True; - xev.xclient.window = m_window; - xev.xclient.message_type = m_system->m_net_state; - xev.xclient.format = 32; - - if (set == True) - xev.xclient.data.l[0] = _NET_WM_STATE_ADD; - else - xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE; - - xev.xclient.data.l[1] = m_system->m_net_max_horz; - xev.xclient.data.l[2] = m_system->m_net_max_vert; - xev.xclient.data.l[3] = 0; - xev.xclient.data.l[4] = 0; - XSendEvent (m_display, RootWindow(m_display, DefaultScreen(m_display)), - False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); -} - -bool GHOST_WindowX11::netwmIsMaximized(void) const -{ - unsigned char *prop_ret; - unsigned long bytes_after, num_ret, i; - Atom type_ret; - bool st; - int format_ret, count; - - prop_ret = NULL; - st = False; - i = XGetWindowProperty(m_display, m_window, m_system->m_net_state, 0, - 0x7fffffff, False, XA_ATOM, &type_ret, &format_ret, - &num_ret, &bytes_after, &prop_ret); - if ((i == Success) && (prop_ret) && (format_ret == 32)) { - count = 0; - for (i = 0; i < num_ret; i++) { - if (((unsigned long *) prop_ret)[i] == m_system->m_net_max_horz) - count++; - if (((unsigned long *) prop_ret)[i] == m_system->m_net_max_vert) - count++; - if (count == 2) { - st = True; - break; - } - } - } - - if (prop_ret) - XFree(prop_ret); - return (st); -} - -void GHOST_WindowX11::netwmFullScreen(bool set) -{ - XEvent xev; - - xev.xclient.type = ClientMessage; - xev.xclient.serial = 0; - xev.xclient.send_event = True; - xev.xclient.window = m_window; - xev.xclient.message_type = m_system->m_net_state; - xev.xclient.format = 32; - - if (set == True) - xev.xclient.data.l[0] = _NET_WM_STATE_ADD; - else - xev.xclient.data.l[0] = _NET_WM_STATE_REMOVE; - - xev.xclient.data.l[1] = m_system->m_net_fullscreen; - xev.xclient.data.l[2] = 0; - xev.xclient.data.l[3] = 0; - xev.xclient.data.l[4] = 0; - XSendEvent (m_display, RootWindow(m_display, DefaultScreen(m_display)), - False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); -} - -bool GHOST_WindowX11::netwmIsFullScreen(void) const -{ - unsigned char *prop_ret; - unsigned long bytes_after, num_ret, i; - Atom type_ret; - bool st; - int format_ret; - - prop_ret = NULL; - st = False; - i = XGetWindowProperty(m_display, m_window, m_system->m_net_state, 0, - 0x7fffffff, False, XA_ATOM, &type_ret, &format_ret, - &num_ret, &bytes_after, &prop_ret); - if ((i == Success) && (prop_ret) && (format_ret == 32)) { - for (i = 0; i < num_ret; i++) { - if (((unsigned long *)prop_ret)[i] == m_system->m_net_fullscreen) { - st = True; - break; - } - } - } - - if (prop_ret) - XFree(prop_ret); - return (st); -} - -void GHOST_WindowX11::motifFullScreen(bool set) -{ - MotifWmHints hints; - - hints.flags = MWM_HINTS_DECORATIONS; - if (set == True) - hints.decorations = 0; - else - hints.decorations = 1; - XChangeProperty(m_display, m_window, m_system->m_motif, - m_system->m_motif, 32, PropModeReplace, - (unsigned char *)&hints, 4); -} - -bool GHOST_WindowX11::motifIsFullScreen(void) const -{ - unsigned char *prop_ret; - unsigned long bytes_after, num_ret; - MotifWmHints *hints; - Atom type_ret; - bool state; - int format_ret, st; - - prop_ret = NULL; - state = False; - st = XGetWindowProperty(m_display, m_window, m_system->m_motif, 0, - 0x7fffffff, False, m_system->m_motif, - &type_ret, &format_ret, &num_ret, - &bytes_after, &prop_ret); - if ((st == Success) && (prop_ret)) { - hints = (MotifWmHints *)prop_ret; - if (hints->flags & MWM_HINTS_DECORATIONS) { - if (!hints->decorations) - state = True; - } - } - - if (prop_ret) - XFree(prop_ret); - return (state); -} - -GHOST_TWindowState GHOST_WindowX11::getState() const -{ - GHOST_TWindowState state_ret; - int state; - - state_ret = GHOST_kWindowStateNormal; - state = icccmGetState(); - /* - * In the Iconic and Withdrawn state, the window is - * unmaped, so only need return a Minimized state. - */ - if ((state == IconicState) || (state == WithdrawnState)) - state_ret = GHOST_kWindowStateMinimized; - else if (netwmIsMaximized() == True) - state_ret = GHOST_kWindowStateMaximized; - else if (netwmIsFullScreen() == True) - state_ret = GHOST_kWindowStateFullScreen; - else if (motifIsFullScreen() == True) - state_ret = GHOST_kWindowStateFullScreen; - return (state_ret); + GHOST_TWindowState +GHOST_WindowX11:: +getState( +) const { + //FIXME + return GHOST_kWindowStateNormal; } -GHOST_TSuccess GHOST_WindowX11::setState(GHOST_TWindowState state) -{ - GHOST_TWindowState cur_state; - bool is_max, is_full, is_motif_full; + GHOST_TSuccess +GHOST_WindowX11:: +setState( + GHOST_TWindowState state +){ + //TODO - cur_state = getState(); - if (state == (int)cur_state) + if (state == (int)getState()) { return GHOST_kSuccess; - - if (cur_state != GHOST_kWindowStateMinimized) { - /* - * The window don't have this property's - * if it's not mapped. - */ - is_max = netwmIsMaximized(); - is_full = netwmIsFullScreen(); - } - else { - is_max = False; - is_full = False; - } - - is_motif_full = motifIsFullScreen(); - - if (state == GHOST_kWindowStateNormal) { - if (is_max == True) - netwmMaximized(False); - if (is_full == True) - netwmFullScreen(False); - if (is_motif_full == True) - motifFullScreen(False); - icccmSetState(NormalState); - return (GHOST_kSuccess); - } - - if (state == GHOST_kWindowStateFullScreen) { - /* - * We can't change to full screen if the window - * isn't mapped. - */ - if (cur_state == GHOST_kWindowStateMinimized) - return (GHOST_kFailure); - - if (is_max == True) - netwmMaximized(False); - if (is_full == False) - netwmFullScreen(True); - if (is_motif_full == False) - motifFullScreen(True); - return (GHOST_kSuccess); - } - - if (state == GHOST_kWindowStateMaximized) { - /* - * We can't change to Maximized if the window - * isn't mapped. - */ - if (cur_state == GHOST_kWindowStateMinimized) - return (GHOST_kFailure); - - if (is_full == True) - netwmFullScreen(False); - if (is_motif_full == True) - motifFullScreen(False); - if (is_max == False) - netwmMaximized(True); - return (GHOST_kSuccess); - } - - if (state == GHOST_kWindowStateMinimized) { - /* - * The window manager need save the current state of - * the window (maximized, full screen, etc). - */ - icccmSetState(IconicState); - return (GHOST_kSuccess); + } else { + return GHOST_kFailure; } - return (GHOST_kFailure); } #include diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 1d73faaf3f6..abb5c131cb7 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -212,15 +212,6 @@ public: const GHOST_TabletData* GetTabletData() { return &m_xtablet.CommonData; } - - /* - * Need this in case that we want start the window - * in FullScreen or Maximized state. - * Check GHOST_WindowX11.cpp - */ - bool m_post_init; - GHOST_TWindowState m_post_state; - protected: /** * Tries to install a rendering context in this window. @@ -336,18 +327,6 @@ private : /* Tablet devices */ XTablet m_xtablet; - - void icccmSetState(int state); - int icccmGetState() const; - - void netwmMaximized(bool set); - bool netwmIsMaximized() const; - - void netwmFullScreen(bool set); - bool netwmIsFullScreen() const; - - void motifFullScreen(bool set); - bool motifIsFullScreen() const; }; -- cgit v1.2.3 From eef475ac7e34dd729dad12b8977c34015cf534a4 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 22 Sep 2008 19:37:30 +0000 Subject: Fix for bug #11163: strand render without tangent shading didn't give correct results. --- source/blender/render/intern/source/shadeinput.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/source/blender/render/intern/source/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 7397d623264..8904999432a 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -343,10 +343,19 @@ void shade_input_set_strand(ShadeInput *shi, StrandRen *strand, StrandPoint *spo VECCOPY(shi->orignor, shi->facenor); /* shade_input_set_normals equivalent */ - if(shi->mat->mode & MA_TANGENT_STR) + if(shi->mat->mode & MA_TANGENT_STR) { VECCOPY(shi->vn, spoint->tan) - else - VECCOPY(shi->vn, spoint->nor) + } + else { + float cross[3]; + + Crossf(cross, spoint->co, spoint->tan); + Crossf(shi->vn, cross, spoint->tan); + Normalize(shi->vn); + + if(INPR(shi->vn, shi->view) < 0.0f) + VecMulf(shi->vn, -1.0f); + } VECCOPY(shi->vno, shi->vn); } -- cgit v1.2.3 From 9b4956ae2213570e07475ecc544a630c44d2892c Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Mon, 22 Sep 2008 19:54:30 +0000 Subject: BGE patch: KX_STATEx constant to allow simple state manipulation in setState() The constants KX_STATE1 to KX_STATE30 can be used with setState() to change the object state in a python controller. The constants are defined in the GameLogic module so that the full name is GameLogic.KX_STATE1 to GameLogic.KX_STATE30 but you can simplify this with the import statement: from GameLogic import * cont = getCurrentController() ob = cont.getOwner() ob.setState(KX_STATE2) #go to state 2 KX_STATEx constants are defined as (1<<(x-1)) Binary operators |, &, ^ and ~ can be used to combine states: You can activate more than one state at a time with the | operator: ob.setState(KX_STATE1|KX_STATE2) #activate state 1 and 2, stop all others You can add a state to the current state mask with: state = ob.getState() ob.setState(state|KX_STATE3) #activate state 3, keep others You can substract a state to the current state mask with the & and operator: state = ob.getState() ob.setState(state&~KX_STATE2) #stop state 2, keep others You can invert a state with the ^ operator: state = ob.getState() ob.setState(state^KX_STATE2) #invert state 2, keep others --- source/gameengine/Ketsji/KX_PythonInit.cpp | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 6b2f3c68d55..95693efe30e 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -975,6 +975,38 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack KX_MACRO_addTypesToDict(d, CAM_POS, BL_Shader::CAM_POS); KX_MACRO_addTypesToDict(d, CONSTANT_TIMER, BL_Shader::CONSTANT_TIMER); + /* 10 state actuator */ + KX_MACRO_addTypesToDict(d, KX_STATE1, (1<<0)); + KX_MACRO_addTypesToDict(d, KX_STATE2, (1<<1)); + KX_MACRO_addTypesToDict(d, KX_STATE3, (1<<2)); + KX_MACRO_addTypesToDict(d, KX_STATE4, (1<<3)); + KX_MACRO_addTypesToDict(d, KX_STATE5, (1<<4)); + KX_MACRO_addTypesToDict(d, KX_STATE6, (1<<5)); + KX_MACRO_addTypesToDict(d, KX_STATE7, (1<<6)); + KX_MACRO_addTypesToDict(d, KX_STATE8, (1<<7)); + KX_MACRO_addTypesToDict(d, KX_STATE9, (1<<8)); + KX_MACRO_addTypesToDict(d, KX_STATE10, (1<<9)); + KX_MACRO_addTypesToDict(d, KX_STATE11, (1<<10)); + KX_MACRO_addTypesToDict(d, KX_STATE12, (1<<11)); + KX_MACRO_addTypesToDict(d, KX_STATE13, (1<<12)); + KX_MACRO_addTypesToDict(d, KX_STATE14, (1<<13)); + KX_MACRO_addTypesToDict(d, KX_STATE15, (1<<14)); + KX_MACRO_addTypesToDict(d, KX_STATE16, (1<<15)); + KX_MACRO_addTypesToDict(d, KX_STATE17, (1<<16)); + KX_MACRO_addTypesToDict(d, KX_STATE18, (1<<17)); + KX_MACRO_addTypesToDict(d, KX_STATE19, (1<<18)); + KX_MACRO_addTypesToDict(d, KX_STATE20, (1<<19)); + KX_MACRO_addTypesToDict(d, KX_STATE21, (1<<20)); + KX_MACRO_addTypesToDict(d, KX_STATE22, (1<<21)); + KX_MACRO_addTypesToDict(d, KX_STATE23, (1<<22)); + KX_MACRO_addTypesToDict(d, KX_STATE24, (1<<23)); + KX_MACRO_addTypesToDict(d, KX_STATE25, (1<<24)); + KX_MACRO_addTypesToDict(d, KX_STATE26, (1<<25)); + KX_MACRO_addTypesToDict(d, KX_STATE27, (1<<26)); + KX_MACRO_addTypesToDict(d, KX_STATE28, (1<<27)); + KX_MACRO_addTypesToDict(d, KX_STATE29, (1<<28)); + KX_MACRO_addTypesToDict(d, KX_STATE30, (1<<29)); + // Check for errors if (PyErr_Occurred()) { -- cgit v1.2.3 From 0cf7bf73576c99897a7838beae7b093d118bb0bb Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 22 Sep 2008 20:26:28 +0000 Subject: Fix for part of bug #17506: uv editing with multires is only allowed at level 1, missed a case. --- source/blender/src/editsima.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/source/blender/src/editsima.c b/source/blender/src/editsima.c index 69070d61bf0..1762e49a2a2 100644 --- a/source/blender/src/editsima.c +++ b/source/blender/src/editsima.c @@ -2654,15 +2654,9 @@ void image_changed(SpaceImage *sima, Image *image) MTFace *tface; EditMesh *em = G.editMesh; EditFace *efa; - ImBuf *ibuf = NULL; + /*ImBuf *ibuf = NULL;*/ short change = 0; - if(image==NULL) { - sima->flag &= ~SI_DRAWTOOL; - } else { - ibuf = BKE_image_get_ibuf(image, NULL); - } - if(sima->mode!=SI_TEXTURE) return; @@ -2675,6 +2669,9 @@ void image_changed(SpaceImage *sima, Image *image) (G.editMesh->faces.first) ) { + if(!is_uv_tface_editing_allowed()) + return; + /* Add a UV layer if there is none, editmode only */ if ( !CustomData_has_layer(&G.editMesh->fdata, CD_MTFACE) ) { EM_add_data_layer(&em->fdata, CD_MTFACE); @@ -2685,6 +2682,11 @@ void image_changed(SpaceImage *sima, Image *image) allqueue(REDRAWVIEW3D, 0); allqueue(REDRAWBUTSEDIT, 0); } + +#if 0 + if(image) + ibuf = BKE_image_get_ibuf(image, NULL); +#endif for (efa= em->faces.first; efa; efa= efa->next) { tface = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); @@ -2714,9 +2716,13 @@ void image_changed(SpaceImage *sima, Image *image) } } } + /* change the space image after because simaFaceDraw_Check uses the space image * to check if the face is displayed in UV-localview */ sima->image = image; + + if(sima->image==NULL) + sima->flag &= ~SI_DRAWTOOL; if (change) object_uvs_changed(OBACT); -- cgit v1.2.3 From d438b466b75d44f1f80dbd1e0bcc6ae27d083461 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Mon, 22 Sep 2008 21:15:48 +0000 Subject: Fix file browser for Windows: going to the parent directory introduces ../\. Correct parent is ..\ under Windows. --- source/blender/blenlib/intern/util.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index 1630842be05..d65fe8a476a 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1060,13 +1060,18 @@ void BLI_makestringcode(const char *relfile, char *file) int BLI_parent_dir(char *path) { +#ifdef WIN32 + static char *parent_dir="..\\"; +#else + static char *parent_dir="../"; +#endif char tmp[FILE_MAXDIR+FILE_MAXFILE+4]; BLI_strncpy(tmp, path, sizeof(tmp)); BLI_add_slash(tmp); - strcat(tmp, "../"); + strcat(tmp, parent_dir); BLI_cleanup_dir(NULL, tmp); - if (!BLI_testextensie(tmp, "../")) { + if (!BLI_testextensie(tmp, parent_dir)) { BLI_strncpy(path, tmp, sizeof(tmp)); return 1; } else { -- cgit v1.2.3 From 2875cc9cc68b9e57e7525d490fd8d57a3eba8653 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 22 Sep 2008 21:22:16 +0000 Subject: Fix for second part of bug #17506: issue with swapped uv coordinates on creating multires in editmode, wasn't doing test_index_face for the face data. --- source/blender/blenkernel/intern/multires.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 9bc7fe28f44..259a4e0de04 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -208,7 +208,7 @@ static void multires_get_edge(MultiresEdge *e, EditEdge *eed, MEdge *m, short *f } } -static void multires_get_face(MultiresFace *f, EditFace *efa, MFace *m) +static void multires_get_face(MultiresFace *f, CustomData *fdata, int findex, EditFace *efa, MFace *m) { if(efa) { MFace tmp; @@ -218,7 +218,7 @@ static void multires_get_face(MultiresFace *f, EditFace *efa, MFace *m) tmp.v3= efa->v3->tmp.l; tmp.v4= 0; if(efa->v4) tmp.v4= efa->v4->tmp.l; - test_index_face(&tmp, NULL, 0, efa->v4?4:3); + test_index_face(&tmp, fdata, findex, efa->v4?4:3); for(j=0; j<4; ++j) f->v[j]= (&tmp.v1)[j]; /* Flags */ @@ -388,7 +388,7 @@ void multires_create(Object *ob, Mesh *me) &me->mr->fdata, CD_MTFACE); if(em) efa= em->faces.first; for(i=0; itotface; ++i) { - multires_get_face(&lvl->faces[i], efa, &me->mface[i]); + multires_get_face(&lvl->faces[i], &me->mr->fdata, i, efa, &me->mface[i]); if(em) efa= efa->next; } @@ -765,7 +765,7 @@ static void multires_update_faces(Mesh *me, EditMesh *em) if(em) efa= em->faces.first; for(i=0; itotface; ++i) { MultiresFace mftmp; - multires_get_face(&mftmp, efa, &me->mface[i]); + multires_get_face(&mftmp, &me->mr->fdata, i, efa, &me->mface[i]); if(cr_lvl->faces[i].flag != mftmp.flag) cr_flag_damaged[i]= 1; if(cr_lvl->faces[i].mat_nr != mftmp.mat_nr) -- cgit v1.2.3 From 18c954e95ba8181a67a6e67246d5f507246db007 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Mon, 22 Sep 2008 21:49:48 +0000 Subject: BGE patch #17569 approved: Make FrameProp: work in Shape Action. PyDoc updated. --- .../Converter/BL_ShapeActionActuator.cpp | 50 ++++++++++++++++++++++ .../gameengine/Converter/BL_ShapeActionActuator.h | 5 +++ .../gameengine/Converter/KX_ConvertActuators.cpp | 2 + source/gameengine/PyDoc/BL_ActionActuator.py | 13 +++++- source/gameengine/PyDoc/BL_ShapeActionActuator.py | 13 +++++- 5 files changed, 79 insertions(+), 4 deletions(-) diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index 721c24dfb94..7a73420fc7c 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -49,6 +49,7 @@ #include "BLI_arithb.h" #include "MT_Matrix4x4.h" #include "BKE_utildefines.h" +#include "FloatValue.h" #include "PyObjectPlus.h" #ifdef HAVE_CONFIG_H @@ -342,6 +343,18 @@ bool BL_ShapeActionActuator::Update(double curtime, bool frame) break; } + /* Set the property if its defined */ + if (m_framepropname[0] != '\0') { + CValue* propowner = GetParent(); + CValue* oldprop = propowner->GetProperty(m_framepropname); + CValue* newval = new CFloatValue(m_localtime); + if (oldprop) { + oldprop->SetValue(newval); + } else { + propowner->SetProperty(m_framepropname, newval); + } + newval->Release(); + } if (bNegativeEvent) m_blendframe=0.0f; @@ -442,6 +455,7 @@ PyMethodDef BL_ShapeActionActuator::Methods[] = { {"setPriority", (PyCFunction) BL_ShapeActionActuator::sPySetPriority, METH_VARARGS, SetPriority_doc}, {"setFrame", (PyCFunction) BL_ShapeActionActuator::sPySetFrame, METH_VARARGS, SetFrame_doc}, {"setProperty", (PyCFunction) BL_ShapeActionActuator::sPySetProperty, METH_VARARGS, SetProperty_doc}, + {"setFrameProperty", (PyCFunction) BL_ShapeActionActuator::sPySetFrameProperty, METH_VARARGS, SetFrameProperty_doc}, {"setBlendtime", (PyCFunction) BL_ShapeActionActuator::sPySetBlendtime, METH_VARARGS, SetBlendtime_doc}, {"getAction", (PyCFunction) BL_ShapeActionActuator::sPyGetAction, METH_NOARGS, GetAction_doc}, @@ -451,6 +465,7 @@ PyMethodDef BL_ShapeActionActuator::Methods[] = { {"getPriority", (PyCFunction) BL_ShapeActionActuator::sPyGetPriority, METH_NOARGS, GetPriority_doc}, {"getFrame", (PyCFunction) BL_ShapeActionActuator::sPyGetFrame, METH_NOARGS, GetFrame_doc}, {"getProperty", (PyCFunction) BL_ShapeActionActuator::sPyGetProperty, METH_NOARGS, GetProperty_doc}, + {"getFrameProperty", (PyCFunction) BL_ShapeActionActuator::sPyGetFrameProperty, METH_NOARGS, GetFrameProperty_doc}, {"getType", (PyCFunction) BL_ShapeActionActuator::sPyGetType, METH_NOARGS, GetType_doc}, {"setType", (PyCFunction) BL_ShapeActionActuator::sPySetType, METH_NOARGS, SetType_doc}, {NULL,NULL} //Sentinel @@ -706,6 +721,20 @@ PyObject* BL_ShapeActionActuator::PySetPriority(PyObject* self, Py_RETURN_NONE; } +/* getProperty */ +const char BL_ShapeActionActuator::GetFrameProperty_doc[] = +"getFrameProperty()\n" +"\tReturns the name of the property, that is set to the current frame number.\n"; + +PyObject* BL_ShapeActionActuator::PyGetFrameProperty(PyObject* self) { + PyObject *result; + + result = Py_BuildValue("s", (const char *)m_framepropname); + + return result; +} + + /* setFrame */ const char BL_ShapeActionActuator::SetFrame_doc[] = "setFrame(frame)\n" @@ -753,6 +782,27 @@ PyObject* BL_ShapeActionActuator::PySetProperty(PyObject* self, Py_RETURN_NONE; } +/* setFrameProperty */ +const char BL_ShapeActionActuator::SetFrameProperty_doc[] = +"setFrameProperty(prop)\n" +"\t - prop : A string specifying the property of the frame set up update.\n"; + +PyObject* BL_ShapeActionActuator::PySetFrameProperty(PyObject* self, + PyObject* args, + PyObject* kwds) { + char *string; + + if (PyArg_ParseTuple(args,"s",&string)) + { + m_framepropname = string; + } + else { + return NULL; + } + + Py_RETURN_NONE; +} + /* getType */ const char BL_ShapeActionActuator::GetType_doc[] = "getType()\n" diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h index a9b9ad8fa86..30b2d41fc67 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.h +++ b/source/gameengine/Converter/BL_ShapeActionActuator.h @@ -42,6 +42,7 @@ public: Py_Header; BL_ShapeActionActuator(SCA_IObject* gameobj, const STR_String& propname, + const STR_String& framepropname, float starttime, float endtime, struct bAction *action, @@ -66,6 +67,7 @@ public: m_playtype(playtype), m_priority(priority), m_action(action), + m_framepropname(framepropname), m_propname(propname) { }; @@ -84,6 +86,7 @@ public: KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetEnd); KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetFrame); KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetProperty); + KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetFrameProperty); KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetBlendtime); KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetChannel); @@ -94,6 +97,7 @@ public: KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetEnd); KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetFrame); KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetProperty); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetFrameProperty); // KX_PYMETHOD(BL_ActionActuator,GetChannel); KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetType); KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetType); @@ -126,6 +130,7 @@ protected: short m_priority; struct bAction *m_action; STR_String m_propname; + STR_String m_framepropname; vector m_blendshape; }; diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index e8be8de95ed..78791c53d7c 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -210,10 +210,12 @@ void BL_ConvertActuators(char* maggiename, if (blenderobject->type==OB_MESH){ bActionActuator* actact = (bActionActuator*) bact->data; STR_String propname = (actact->name ? actact->name : ""); + STR_String propframe = (actact->frameProp ? actact->frameProp : ""); BL_ShapeActionActuator* tmpbaseact = new BL_ShapeActionActuator( gameobj, propname, + propframe, actact->sta, actact->end, actact->act, diff --git a/source/gameengine/PyDoc/BL_ActionActuator.py b/source/gameengine/PyDoc/BL_ActionActuator.py index d56888cde80..b68d3014115 100644 --- a/source/gameengine/PyDoc/BL_ActionActuator.py +++ b/source/gameengine/PyDoc/BL_ActionActuator.py @@ -164,5 +164,14 @@ class BL_ActionActuator(SCA_IActuator): @param mode: True for armature/world space, False for bone space @type mode: boolean """ - - + def setFrameProperty(prop): + """ + @param prop: A string specifying the property of the object that will be updated with the action frame number. + @type prop: string + """ + def getFrameProperty(): + """ + Returns the name of the property that is set to the current frame number. + + @rtype: string + """ diff --git a/source/gameengine/PyDoc/BL_ShapeActionActuator.py b/source/gameengine/PyDoc/BL_ShapeActionActuator.py index 63cce253fa4..a26b276a2da 100644 --- a/source/gameengine/PyDoc/BL_ShapeActionActuator.py +++ b/source/gameengine/PyDoc/BL_ShapeActionActuator.py @@ -154,5 +154,14 @@ class BL_ShapeActionActuator(SCA_IActuator): @rtype: string """ - - + def setFrameProperty(prop): + """ + @param prop: A string specifying the property of the object that will be updated with the action frame number. + @type prop: string + """ + def getFrameProperty(): + """ + Returns the name of the property that is set to the current frame number. + + @rtype: string + """ -- cgit v1.2.3 From 7a28ca4398465be1d6d57079e4b27c3a03418745 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 23 Sep 2008 00:37:19 +0000 Subject: Make GameLogic work for python autocomplete (after running the BGE once at least) only clear newly added items from the gameLogic dictionary rather then the whole dictionary. --- .../BlenderRoutines/BL_KetsjiEmbedStart.cpp | 23 +++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 74fe6c68863..6a296a3e244 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -326,8 +326,10 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, ketsjiengine->SetPythonDictionary(dictionaryobject); initRasterizer(rasterizer, canvas); PyObject *gameLogic = initGameLogic(ketsjiengine, startscene); - PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module. PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module. + PyObject *gameLogic_keys = PyDict_Keys(PyModule_GetDict(gameLogic)); + PyDict_SetItemString(dictionaryobject, "GameLogic", gameLogic); // Same as importing the module. + initGameKeys(); initPythonConstraintBinding(); initMathutils(); @@ -401,8 +403,20 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, // inside the GameLogic dictionary when the python interpreter is finalized. // which allows the scene to safely delete them :) // see: (space.c)->start_game - PyDict_Clear(PyModule_GetDict(gameLogic)); - PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); + + //PyDict_Clear(PyModule_GetDict(gameLogic)); + + // Keep original items, means python plugins will autocomplete members + int listIndex; + PyObject *gameLogic_keys_new = PyDict_Keys(PyModule_GetDict(gameLogic)); + for (listIndex=0; listIndex < PyList_Size(gameLogic_keys_new); listIndex++) { + PyObject* item = PyList_GET_ITEM(gameLogic_keys_new, listIndex); + if (!PySequence_Contains(gameLogic_keys, item)) { + PyDict_DelItem( PyModule_GetDict(gameLogic), item); + } + } + Py_DECREF(gameLogic_keys_new); + gameLogic_keys_new = NULL; ketsjiengine->StopEngine(); exitGamePythonScripting(); @@ -413,6 +427,9 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, delete sceneconverter; sceneconverter = NULL; } + + Py_DECREF(gameLogic_keys); + gameLogic_keys = NULL; } // set the cursor back to normal canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL); -- cgit v1.2.3 From 872704010e5f97291b65a7d5a4bfd5349e896aaf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 23 Sep 2008 00:49:44 +0000 Subject: [#8540] Import scripts for MilkShape3D file formats from Markus Ilmola (glome) note, UV's will be incorrect in some faces because of eekadoodle problem. --- release/scripts/ms3d_import_ascii.py | 479 +++++++++++++++++++++++++++++++++++ 1 file changed, 479 insertions(+) create mode 100644 release/scripts/ms3d_import_ascii.py diff --git a/release/scripts/ms3d_import_ascii.py b/release/scripts/ms3d_import_ascii.py new file mode 100644 index 00000000000..d8c22a1ec99 --- /dev/null +++ b/release/scripts/ms3d_import_ascii.py @@ -0,0 +1,479 @@ +#!BPY +""" +Name: 'MilkShape3D ASCII (.txt)...' +Blender: 245 +Group: 'Import' +Tooltip: 'Import from a MilkShape3D ASCII file format (.txt)' +""" +# +# Author: Markus Ilmola +# Email: markus.ilmola@pp.inet.fi +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +# import needed stuff +import os.path +import re +import math +from math import * +import Blender +from Blender import Mathutils +from Blender.Mathutils import * + + + +# Converts ms3d euler angles to a rotation matrix +def RM(a): + sy = sin(a[2]) + cy = cos(a[2]) + sp = sin(a[1]) + cp = cos(a[1]) + sr = sin(a[0]) + cr = cos(a[0]) + return Matrix([cp*cy, cp*sy, -sp], [sr*sp*cy+cr*-sy, sr*sp*sy+cr*cy, sr*cp],[cr*sp*cy+-sr*-sy, cr*sp*sy+-sr*cy, cr*cp]) + + +# Converts ms3d euler angles to a quaternion +def RQ(a): + angle = a[2] * 0.5; + sy = sin(angle); + cy = cos(angle); + angle = a[1] * 0.5; + sp = sin(angle); + cp = cos(angle); + angle = a[0] * 0.5; + sr = sin(angle); + cr = cos(angle); + return Quaternion(cr*cp*cy+sr*sp*sy, sr*cp*cy-cr*sp*sy, cr*sp*cy+sr*cp*sy, cr*cp*sy-sr*sp*cy) + + +# takes a texture filename and tries to load it +def loadImage(path, filename): + image = None + try: + image = Blender.Image.Load(os.path.abspath(filename)) + except IOError: + print "Warning: Failed to load image: " + filename + ". Trying short path instead...\n" + try: + image = Blender.Image.Load(os.path.dirname(path) + "/" + os.path.basename(filename)) + except IOError: + print "Warning: Failed to load image: " + os.path.basename(filename) + "!\n" + return image + + + +# returns the next non-empty, non-comment line from the file +def getNextLine(file): + ready = False + while ready==False: + line = file.readline() + if len(line)==0: + print "Warning: End of file reached." + return line + ready = True + line = line.strip() + if len(line)==0 or line.isspace(): + ready = False + if len(line)>=2 and line[0]=='/' and line[1]=='/': + ready = False + return line + + + +# imports a MilkShape3D ascii file to the current scene +def import_ms3d_ascii(path): + # limits + MAX_NUMMESHES = 1000 + MAX_NUMVERTS = 100000 + MAX_NUMNORMALS = 100000 + MAX_NUMTRIS = 100000 + MAX_NUMMATS = 16 + MAX_NUMBONES = 100 + MAX_NUMPOSKEYS = 1000 + MAX_NUMROTKEYS = 1000 + + # get scene + scn = Blender.Scene.GetCurrent() + if scn==None: + return "No scene to import to!" + + # open the file + try: + file = open(path, 'r') + except IOError: + return "Failed to open the file!" + + # Read frame info + try: + lines = getNextLine(file).split() + if len(lines) != 2 or lines[0] != "Frames:": + raise ValueError + lines = getNextLine(file).split() + if len(lines) != 2 or lines[0] != "Frame:": + raise ValueError + except ValueError: + return "Frame information is invalid!" + + # Create the mesh + meshOb = Blender.Object.New('Mesh', "MilkShape3D Object") + mesh = Blender.Mesh.New("MilkShape3D Mesh") + meshOb.link(mesh) + scn.objects.link(meshOb) + + # read the number of meshes + try: + lines = getNextLine(file).split() + if len(lines)!=2 or lines[0]!="Meshes:": + raise ValueError + numMeshes = int(lines[1]) + if numMeshes < 0 or numMeshes > MAX_NUMMESHES: + raise ValueError + except ValueError: + return "Number of meshes is invalid!" + + # read meshes + vertBase = 0 + faceBase = 0 + boneIds = [] + for i in range(numMeshes): + # read name, flags and material + try: + lines = re.findall(r'\".*\"|[^ ]+', getNextLine(file)) + if len(lines)!=3: + raise ValueError + material = int(lines[2]) + except ValueError: + return "Name, flags or material in mesh " + str(i+1) + " are invalid!" + + # read the number of vertices + try: + numVerts = int(getNextLine(file)) + if numVerts < 0 or numVerts > MAX_NUMVERTS: + raise ValueError + except ValueError: + return "Number of vertices in mesh " + str(i+1) + " is invalid!" + + # read vertices + coords = [] + uvs = [] + for j in xrange(numVerts): + try: + lines = getNextLine(file).split() + if len(lines)!=7: + raise ValueError + coords.append([float(lines[1]), float(lines[2]), float(lines[3])]) + uvs.append([float(lines[4]), 1-float(lines[5])]) + boneIds.append(int(lines[6])) + except ValueError: + return "Vertex " + str(j+1) + " in mesh " + str(i+1) + " is invalid!" + mesh.verts.extend(coords) + + # read number of normals + try: + numNormals = int(getNextLine(file)) + if numNormals < 0 or numNormals > MAX_NUMNORMALS: + raise ValueError + except ValueError: + return "Number of normals in mesh " + str(i+1) + " is invalid!" + + # read normals + normals = [] + for j in xrange(numNormals): + try: + lines = getNextLine(file).split() + if len(lines)!=3: + raise ValueError + normals.append([float(lines[0]), float(lines[1]), float(lines[2])]) + except ValueError: + return "Normal " + str(j+1) + " in mesh " + str(i+1) + " is invalid!" + + # read the number of triangles + try: + numTris = int(getNextLine(file)) + if numTris < 0 or numTris > MAX_NUMTRIS: + raise ValueError + except ValueError: + return "Number of triangles in mesh " + str(i+1) + " is invalid!" + + # read triangles + faces = [] + for j in xrange(numTris): + # read the triangle + try: + lines = getNextLine(file).split() + if len(lines)!=8: + raise ValueError + v1 = int(lines[1]) + v2 = int(lines[2]) + v3 = int(lines[3]) + faces.append([v1+vertBase, v2+vertBase, v3+vertBase]) + except ValueError: + return "Triangle " + str(j+1) + " in mesh " + str(i+1) + " is invalid!" + mesh.faces.extend(faces) + + # set texture coordinates and material + for j in xrange(faceBase, len(mesh.faces)): + face = mesh.faces[j] + face.uv = [Vector(uvs[face.verts[0].index-vertBase]), Vector(uvs[face.verts[1].index-vertBase]), Vector(uvs[face.verts[2].index-vertBase])] + if material>=0: + face.mat = material + + # increase vertex and face base + vertBase = len(mesh.verts) + faceBase = len(mesh.faces) + + # read the number of materials + try: + lines = getNextLine(file).split() + if len(lines)!=2 or lines[0]!="Materials:": + raise ValueError + numMats = int(lines[1]) + if numMats < 0 or numMats > MAX_NUMMATS: + raise ValueError + except ValueError: + return "Number of materials is invalid!" + + # read the materials + for i in range(numMats): + # read name + name = getNextLine(file)[1:-1] + + # create the material + mat = Blender.Material.New(name) + mesh.materials += [mat] + + # read ambient color + try: + lines = getNextLine(file).split() + if len(lines)!=4: + raise ValueError + amb = (float(lines[0])+float(lines[1])+float(lines[2]))/3 + mat.setAmb(amb) + except ValueError: + return "Ambient color in material " + str(i+1) + " is invalid!" + + # read diffuse color + try: + lines = getNextLine(file).split() + if len(lines)!=4: + raise ValueError + mat.setRGBCol([float(lines[0]), float(lines[1]), float(lines[2])]) + except ValueError: + return "Diffuse color in material " + str(i+1) + " is invalid!" + + # read specular color + try: + lines = getNextLine(file).split() + if len(lines)!=4: + raise ValueError + mat.setSpecCol([float(lines[0]), float(lines[1]), float(lines[2])]) + except ValueError: + return "Specular color in material " + str(i+1) + " is invalid!" + + # read emissive color + try: + lines = getNextLine(file).split() + if len(lines)!=4: + raise ValueError + emit = (float(lines[0])+float(lines[1])+float(lines[2]))/3 + mat.setEmit(emit) + except ValueError: + return "Emissive color in material " + str(i+1) + " is invalid!" + + # read shininess + try: + shi = float(getNextLine(file)) + #mat.setHardness(int(shi)) + except ValueError: + return "Shininess in material " + str(i+1) + " is invalid!" + + # read transparency + try: + alpha = float(getNextLine(file)) + mat.setAlpha(alpha) + if alpha < 1: + mat.mode |= Blender.Material.Modes.ZTRANSP + except ValueError: + return "Transparency in material " + str(i+1) + " is invalid!" + + # read texturemap + texturemap = getNextLine(file)[1:-1] + if len(texturemap)>0: + colorTexture = Blender.Texture.New(name + "_texture") + colorTexture.setType('Image') + colorTexture.setImage(loadImage(path, texturemap)) + mat.setTexture(0, colorTexture, Blender.Texture.TexCo.UV, Blender.Texture.MapTo.COL) + + # read alphamap + alphamap = getNextLine(file)[1:-1] + if len(alphamap)>0: + alphaTexture = Blender.Texture.New(name + "_alpha") + alphaTexture.setType('Image') + alphaTexture.setImage(loadImage(path, alphamap)) + mat.setTexture(1, alphaTexture, Blender.Texture.TexCo.UV, Blender.Texture.MapTo.ALPHA) + + # read the number of bones + try: + lines = getNextLine(file).split() + if len(lines)!=2 or lines[0]!="Bones:": + raise ValueError + numBones = int(lines[1]) + if numBones < 0 or numBones > MAX_NUMBONES: + raise ValueError + except: + return "Number of bones is invalid!" + + # create the armature + armature = None + armOb = None + if numBones > 0: + armOb = Blender.Object.New('Armature', "MilkShape3D Skeleton") + armature = Blender.Armature.New("MilkShape3D Skeleton") + armature.drawType = Blender.Armature.STICK + armOb.link(armature) + scn.objects.link(armOb) + armOb.makeParentDeform([meshOb]) + armature.makeEditable() + + # read bones + posKeys = {} + rotKeys = {} + for i in range(numBones): + # read name + name = getNextLine(file)[1:-1] + + # create the bone + bone = Blender.Armature.Editbone() + armature.bones[name] = bone + + # read parent + parent = getNextLine(file)[1:-1] + if len(parent)>0: + bone.parent = armature.bones[parent] + + # read position and rotation + try: + lines = getNextLine(file).split() + if len(lines) != 7: + raise ValueError + pos = [float(lines[1]), float(lines[2]), float(lines[3])] + rot = [float(lines[4]), float(lines[5]), float(lines[6])] + except ValueError: + return "Invalid position or orientation in a bone!" + + # set position and orientation + if bone.hasParent(): + bone.head = Vector(pos) * bone.parent.matrix + bone.parent.head + bone.tail = bone.head + Vector([1,0,0]) + tempM = RM(rot) * bone.parent.matrix + tempM.transpose; + bone.matrix = tempM + else: + bone.head = Vector(pos) + bone.tail = bone.head + Vector([1,0,0]) + bone.matrix = RM(rot) + + # Create vertex group for this bone + mesh.addVertGroup(name) + vgroup = [] + for index, v in enumerate(boneIds): + if v==i: + vgroup.append(index) + mesh.assignVertsToGroup(name, vgroup, 1.0, 1) + + # read the number of position key frames + try: + numPosKeys = int(getNextLine(file)) + if numPosKeys < 0 or numPosKeys > MAX_NUMPOSKEYS: + raise ValueError + except ValueError: + return "Invalid number of position key frames!" + + # read position key frames + posKeys[name] = [] + for j in range(numPosKeys): + # read time and position + try: + lines = getNextLine(file).split() + if len(lines) != 4: + raise ValueError + time = float(lines[0]) + pos = [float(lines[1]), float(lines[2]), float(lines[3])] + posKeys[name].append([time, pos]) + except ValueError: + return "Invalid position key frame!" + + # read the number of rotation key frames + try: + numRotKeys = int(getNextLine(file)) + if numRotKeys < 0 or numRotKeys > MAX_NUMROTKEYS: + raise ValueError + except ValueError: + return "Invalid number of rotation key frames!" + + # read rotation key frames + rotKeys[name] = [] + for j in range(numRotKeys): + # read time and rotation + try: + lines = getNextLine(file).split() + if len(lines) != 4: + raise ValueError + time = float(lines[0]) + rot = [float(lines[1]), float(lines[2]), float(lines[3])] + rotKeys[name].append([time, rot]) + except ValueError: + return "Invalid rotation key frame!" + + # create action and pose + action = None + pose = None + if armature != None: + armature.update() + pose = armOb.getPose() + action = armOb.getAction() + if not action: + action = Blender.Armature.NLA.NewAction() + action.setActive(armOb) + + # create animation key frames + for name, pbone in pose.bones.items(): + # create position keys + for key in posKeys[name]: + pbone.loc = Vector(key[1]) + pbone.insertKey(armOb, int(key[0]+0.5), Blender.Object.Pose.LOC, True) + + # create rotation keys + for key in rotKeys[name]: + pbone.quat = RQ(key[1]) + pbone.insertKey(armOb, int(key[0]+0.5), Blender.Object.Pose.ROT, True) + + # set the imported object to be the selected one + scn.objects.selected = [] + meshOb.sel= 1 + Blender.Redraw() + + # The import was a succes! + return "" + + +# load the model +def fileCallback(filename): + error = import_ms3d_ascii(filename) + if error!="": + Blender.Draw.PupMenu("An error occured during import: " + error + "|Not all data might have been imported succesfully.", 2) + +Blender.Window.FileSelector(fileCallback, 'Import') -- cgit v1.2.3 From f187d680d8db02cca6d379ded069cea136169e8a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 23 Sep 2008 01:28:42 +0000 Subject: fix for [#13825] Lack of Flags in Face Mode Set undo was also not working. --- source/blender/src/editmesh_tools.c | 35 +++++++++++++++++++++++++++++------ source/blender/src/filesel.c | 4 +--- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c index 4cf3b410393..ae4bc056964 100644 --- a/source/blender/src/editmesh_tools.c +++ b/source/blender/src/editmesh_tools.c @@ -5483,7 +5483,11 @@ void mesh_set_face_flags(short mode) EditMesh *em = G.editMesh; EditFace *efa; MTFace *tface; - short m_tex=0, m_tiles=0, m_shared=0, m_light=0, m_invis=0, m_collision=0, m_twoside=0, m_obcolor=0; + short m_tex=0, m_tiles=0, m_shared=0, + m_light=0, m_invis=0, m_collision=0, + m_twoside=0, m_obcolor=0, m_halo=0, + m_billboard=0, m_shadow=0, m_text=0, + m_sort=0; short flag = 0, change = 0; if (!EM_texFaceCheck()) { @@ -5493,16 +5497,26 @@ void mesh_set_face_flags(short mode) add_numbut(0, TOG|SHO, "Texture", 0, 0, &m_tex, NULL); add_numbut(1, TOG|SHO, "Tiles", 0, 0, &m_tiles, NULL); - add_numbut(2, TOG|SHO, "Shared", 0, 0, &m_shared, NULL); - add_numbut(3, TOG|SHO, "Light", 0, 0, &m_light, NULL); - add_numbut(4, TOG|SHO, "Invisible", 0, 0, &m_invis, NULL); - add_numbut(5, TOG|SHO, "Collision", 0, 0, &m_collision, NULL); + add_numbut(2, TOG|SHO, "Light", 0, 0, &m_light, NULL); + add_numbut(3, TOG|SHO, "Invisible", 0, 0, &m_invis, NULL); + add_numbut(4, TOG|SHO, "Collision", 0, 0, &m_collision, NULL); + add_numbut(5, TOG|SHO, "Shared", 0, 0, &m_shared, NULL); add_numbut(6, TOG|SHO, "Twoside", 0, 0, &m_twoside, NULL); add_numbut(7, TOG|SHO, "ObColor", 0, 0, &m_obcolor, NULL); + add_numbut(8, TOG|SHO, "Halo", 0, 0, &m_halo, NULL); + add_numbut(9, TOG|SHO, "Billboard", 0, 0, &m_billboard, NULL); + add_numbut(10, TOG|SHO, "Shadow", 0, 0, &m_shadow, NULL); + add_numbut(11, TOG|SHO, "Text", 0, 0, &m_text, NULL); + add_numbut(12, TOG|SHO, "Sort", 0, 0, &m_sort, NULL); - if (!do_clever_numbuts((mode ? "Set Flags" : "Clear Flags"), 8, REDRAW)) + if (!do_clever_numbuts((mode ? "Set Flags" : "Clear Flags"), 13, REDRAW)) return; + /* these 2 cant both be on */ + if (mode) /* are we seeting*/ + if (m_halo) + m_billboard = 0; + if (m_tex) flag |= TF_TEX; if (m_tiles) flag |= TF_TILES; if (m_shared) flag |= TF_SHAREDCOL; @@ -5511,6 +5525,14 @@ void mesh_set_face_flags(short mode) if (m_collision) flag |= TF_DYNAMIC; if (m_twoside) flag |= TF_TWOSIDE; if (m_obcolor) flag |= TF_OBCOL; + if (m_halo) flag |= TF_BILLBOARD; + if (m_billboard) flag |= TF_BILLBOARD2; + if (m_shadow) flag |= TF_SHADOW; + if (m_text) flag |= TF_BMFONT; + if (m_sort) flag |= TF_ALPHASORT; + + if (flag==0) + return; efa= em->faces.first; while(efa) { @@ -5518,6 +5540,7 @@ void mesh_set_face_flags(short mode) tface= CustomData_em_get(&em->fdata, efa->data, CD_MTFACE); if (mode) tface->mode |= flag; else tface->mode &= ~flag; + change = 1; } efa= efa->next; } diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c index 22f7e577ad9..ee1fc523395 100644 --- a/source/blender/src/filesel.c +++ b/source/blender/src/filesel.c @@ -554,9 +554,7 @@ static void split_sfile(SpaceFile *sfile, char *s1) void parent(SpaceFile *sfile) -{ - char path[sizeof(sfile->dir)+4]; - +{ /* if databrowse: no parent */ if(sfile->type==FILE_MAIN && filesel_has_func(sfile)) return; -- cgit v1.2.3 From d2d56e30589caf5bf14f39f21c6a0321e0c01d65 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Tue, 23 Sep 2008 05:00:00 +0000 Subject: bugfix for [#7006] Sleeping Objects losing Ghost Constraint Bullet logic bug in (de)activation/island management: deactivated 'fantom' objects do merge islands, in particular when connected by constraints. (fantom = object with collision detection but no collision response). --- .../BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp | 2 +- .../bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp index 1cc78f76acd..9f8e27a4407 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSimulationIslandManager.cpp @@ -105,7 +105,7 @@ void btSimulationIslandManager::storeIslandActivationState(btCollisionWorld* col for (i=0;igetCollisionObjectArray().size();i++) { btCollisionObject* collisionObject= colWorld->getCollisionObjectArray()[i]; - if (collisionObject->mergesSimulationIslands()) + if (!collisionObject->isStaticOrKinematicObject()) { collisionObject->setIslandTag( m_unionFind.find(index) ); collisionObject->setCompanionId(-1); diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index e46c4e6136b..329a1d9cde3 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -688,8 +688,8 @@ void btDiscreteDynamicsWorld::calculateSimulationIslands() const btRigidBody* colObj0 = &constraint->getRigidBodyA(); const btRigidBody* colObj1 = &constraint->getRigidBodyB(); - if (((colObj0) && ((colObj0)->mergesSimulationIslands())) && - ((colObj1) && ((colObj1)->mergesSimulationIslands()))) + if (((colObj0) && (!(colObj0)->isStaticOrKinematicObject())) && + ((colObj1) && (!(colObj1)->isStaticOrKinematicObject()))) { if (colObj0->isActive() || colObj1->isActive()) { -- cgit v1.2.3 From bcba8003c01d50ffb524092b08026441bbbe4f85 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 23 Sep 2008 06:26:48 +0000 Subject: changing the number of subdivisions for nurbs curves. this way each edge/segment gets the same number of points matching the resolution value. before, a nurbs curve would have the same number of points no matter if it was cyclic or not. This will make slight changes to objects on an animated path, but only noticable if the path has a low resolution. bug [#11744] NurbCurve Radius incorrect - now dosnt show bad results with order 4 on non-cyclic curve. --- source/blender/blenkernel/BKE_curve.h | 7 +++++-- source/blender/blenkernel/intern/anim.c | 3 ++- source/blender/blenkernel/intern/curve.c | 8 ++++---- source/blender/blenkernel/intern/displist.c | 5 +++-- source/blender/src/editcurve.c | 4 ++-- 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 45d8193b16f..006e3ac1e79 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -39,9 +39,12 @@ struct ListBase; struct BezTriple; struct BevList; -#define KNOTSU(nu) ( (nu)->orderu+ (nu)->pntsu+ (nu->orderu-1)*((nu)->flagu & CU_CYCLIC) ) -#define KNOTSV(nu) ( (nu)->orderv+ (nu)->pntsv+ (nu->orderv-1)*((nu)->flagv & CU_CYCLIC) ) +#define KNOTSU(nu) ( (nu)->orderu+ (nu)->pntsu+ (((nu)->flagu & CU_CYCLIC) ? (nu->orderu-1) : 0) ) +#define KNOTSV(nu) ( (nu)->orderv+ (nu)->pntsv+ (((nu)->flagv & CU_CYCLIC) ? (nu->orderv-1) : 0) ) +/* Non cyclic nurbs have 1 less segment */ +#define SEGMENTSU(nu) ( ((nu)->flagu & CU_CYCLIC) ? (nu)->pntsu : (nu)->pntsu-1 ) +#define SEGMENTSV(nu) ( ((nu)->flagv & CU_CYCLIC) ? (nu)->pntsv : (nu)->pntsv-1 ) void unlink_curve( struct Curve *cu); void free_curve( struct Curve *cu); diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index ceb0e132ff9..731c2a18c55 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -52,6 +52,7 @@ #include "DNA_vfont_types.h" #include "BKE_anim.h" +#include "BKE_curve.h" #include "BKE_DerivedMesh.h" #include "BKE_displist.h" #include "BKE_effect.h" @@ -118,7 +119,7 @@ void calc_curvepath(Object *ob) path->len= tot+1; /* exception: vector handle paths and polygon paths should be subdivided at least a factor resolu */ - if(path->lenresolu*nu->pntsu) path->len= nu->resolu*nu->pntsu; + if(path->lenresolu*SEGMENTSU(nu)) path->len= nu->resolu*SEGMENTSU(nu); dist= (float *)MEM_mallocN((tot+1)*4, "calcpathdist"); diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index c5ad9e58a4c..49d25b0652d 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -825,8 +825,8 @@ void makeNurbcurve(Nurb *nu, float *data, int resolu, int dim) len= nu->pntsu; if(len==0) return; sum= (float *)MEM_callocN(sizeof(float)*len, "makeNurbcurve1"); - - resolu*= nu->pntsu; + + resolu= (resolu*SEGMENTSU(nu))+1; if(resolu==0) { MEM_freeN(sum); return; @@ -836,7 +836,7 @@ void makeNurbcurve(Nurb *nu, float *data, int resolu, int dim) ustart= fp[nu->orderu-1]; if(nu->flagu & CU_CYCLIC) uend= fp[nu->pntsu+nu->orderu-1]; else uend= fp[nu->pntsu]; - ustep= (uend-ustart)/(resolu-1+(nu->flagu & CU_CYCLIC)); + ustep= (uend-ustart)/(resolu-1); basisu= (float *)MEM_mallocN(sizeof(float)*KNOTSU(nu), "makeNurbcurve3"); if(nu->flagu & CU_CYCLIC) cycl= nu->orderu-1; @@ -1620,7 +1620,7 @@ void makeBevelList(Object *ob) } else if((nu->type & 7)==CU_NURBS) { if(nu->pntsv==1) { - len= resolu*nu->pntsu; + len= (resolu*SEGMENTSU(nu))+1; bl= MEM_mallocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList3"); BLI_addtail(&(cu->bev), bl); bl->nr= len; diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 69c8f3406a2..e55006b6c1c 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -858,7 +858,8 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) } } else if((nu->type & 7)==CU_NURBS) { - len= nu->pntsu*resolu; + len= (resolu*SEGMENTSU(nu))+1; + dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); BLI_addtail(dispbase, dl); @@ -1322,7 +1323,7 @@ void makeDispListSurf(Object *ob, ListBase *dispbase, int forRender) for (nu=nubase->first; nu; nu=nu->next) { if(forRender || nu->hide==0) { if(nu->pntsv==1) { - len= nu->pntsu*nu->resolu; + len= nu->resolu*SEGMENTSU(nu)+1; dl= MEM_callocN(sizeof(DispList), "makeDispListsurf"); dl->verts= MEM_callocN(len*3*sizeof(float), "dlverts"); diff --git a/source/blender/src/editcurve.c b/source/blender/src/editcurve.c index f15ffcdcb58..1dee0837445 100644 --- a/source/blender/src/editcurve.c +++ b/source/blender/src/editcurve.c @@ -1727,7 +1727,7 @@ void subdivideNurb() */ /* count */ if(nu->flagu & CU_CYCLIC) { - a= nu->pntsu*nu->pntsv; + a= nu->pntsu; bp= nu->bp; prevbp= bp+(a-1); } @@ -2145,7 +2145,7 @@ int convertspline(short type, Nurb *nu) nu->type |= 1; calchandlesNurb(nu); } - else if(type==4) { /* to Nurb */ + else if(type==CU_NURBS) { nu->type &= ~7; nu->type+= 4; nu->orderu= 4; -- cgit v1.2.3 From a55d5918985f58ff3ea52bf78a7bc84d35d483c8 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Tue, 23 Sep 2008 11:51:40 +0000 Subject: "Fix" for [#17671] Particles spin out of control and pass through when hitting collision object -The fix is that particle random size factor should never ever be bigger than 1.0, else negative sizes are possible! Don't know who to blame, but probably my self :) -The second issue of passing through the deflection and rotating wildly around strange centers is not a bug, but for particles the group and object visualization objects have to be centered on the global origin. I'll probably make an option later to use the object center, but this is how things are for now. --- source/blender/src/buttons_object.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 4f98ade9cde..2cd1bc80223 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -4379,7 +4379,7 @@ static void object_panel_particle_extra(Object *ob) /* size changes must create a recalc event always so that sizes are updated properly */ uiDefButF(block, NUM, B_PART_RECALC, "Size:", butx,(buty-=buth),butw,buth, &part->size, 0.01, 100, 10, 1, "The size of the particles"); - uiDefButF(block, NUM, B_PART_RECALC, "Rand:", butx,(buty-=buth),butw,buth, &part->randsize, 0.0, 2.0, 10, 1, "Give the particle size a random variation"); + uiDefButF(block, NUM, B_PART_RECALC, "Rand:", butx,(buty-=buth),butw,buth, &part->randsize, 0.0, 1.0, 10, 1, "Give the particle size a random variation"); uiDefButBitI(block, TOG, PART_SIZEMASS, B_PART_RECALC, "Mass from size", butx,(buty-=buth),butw,buth, &part->flag, 0, 0, 0, 0, "Multiply mass with particle size"); uiDefButF(block, NUM, B_PART_RECALC, "Mass:", butx,(buty-=buth),butw,buth, &part->mass, 0.01, 100, 10, 1, "Specify the mass of the particles"); -- cgit v1.2.3 From 47032c251dd94939bc74cd2b4d0166c567b98888 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Tue, 23 Sep 2008 12:53:00 +0000 Subject: - Particle-particle effectors we're quite unstable and not accurate at all. Now this should be fixed (especially with other integrators than euler) as the needed inter-frame effector particle positions are interpolated properly from the current and previous positions (previously only the most recent position was used). - In practice this removes the dependency of particle simulations from the update order of objects and different particle systems inside objects. - As a nice side effect out of this we also get fully correct birth positions for "near reactor particles" (previously for example smoke trail reactor particles were not born smoothly along the target particles path). --- source/blender/blenkernel/intern/particle.c | 41 ++- source/blender/blenkernel/intern/particle_system.c | 350 ++++++++++----------- source/blender/makesdna/DNA_particle_types.h | 2 + 3 files changed, 209 insertions(+), 184 deletions(-) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 3ff57f55992..38f480f39b8 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3721,6 +3721,7 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey float cfra; int totpart=psys->totpart, between=0; + /* negative time means "use current time" */ if(state->time>0) cfra=state->time; else @@ -3796,7 +3797,45 @@ int psys_get_particle_state(Object *ob, ParticleSystem *psys, int p, ParticleKey } else{ if (pa) { /* TODO PARTICLE - should this ever be NULL? - Campbell */ - copy_particle_key(state,&pa->state,0); + if(pa->state.time==state->time) + copy_particle_key(state, &pa->state, 1); + else if(pa->prev_state.time==state->time) + copy_particle_key(state, &pa->prev_state, 1); + else { + /* let's interpolate to try to be as accurate as possible */ + if(pa->state.time + 1.0f > state->time && pa->prev_state.time - 1.0f < state->time) { + ParticleKey keys[4]; + float dfra, keytime, frs_sec = G.scene->r.frs_sec; + + if(pa->prev_state.time >= pa->state.time) { + /* prev_state is wrong so let's not use it, this can happen at frame 1 or particle birth */ + copy_particle_key(state, &pa->state, 1); + + VECADDFAC(state->co, state->co, state->vel, (state->time-pa->state.time)/frs_sec); + } + else { + copy_particle_key(keys+1, &pa->prev_state, 1); + copy_particle_key(keys+2, &pa->state, 1); + + dfra = keys[2].time - keys[1].time; + + keytime = (state->time - keys[1].time) / dfra; + + /* convert velocity to timestep size */ + VecMulf(keys[1].vel, dfra / frs_sec); + VecMulf(keys[2].vel, dfra / frs_sec); + + interpolate_particle(-1, keys, keytime, state, 1); + + /* convert back to real velocity */ + VecMulf(state->vel, frs_sec / dfra); + } + } + else { + /* extrapolating over big ranges is not accurate so let's just give something close to reasonable back */ + copy_particle_key(state, &pa->state, 0); + } + } if(pa->alive==PARS_DEAD && part->flag&PART_STICKY && pa->flag&PARS_STICKY && pa->stick_ob){ key_from_object(pa->stick_ob,state); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 7aff0f0eb49..0b5a2b71119 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1714,10 +1714,8 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi tob=ob; tpsys=BLI_findlink(&tob->particlesystem,psys->target_psys-1); - - /*TODO: get precise location of particle at birth*/ - state.time=cfra; + state.time = pa->time; if(pa->num == -1) memset(&state, 0, sizeof(state)); else @@ -1809,6 +1807,12 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi } /* conversion done so now we apply new: */ /* -velocity from: */ + + /* *reactions */ + if(dtime>0.0f){ + VECSUB(vel,pa->state.vel,pa->prev_state.vel); + } + /* *emitter velocity */ if(dtime!=0.0 && part->obfac!=0.0){ VECSUB(vel,loc,pa->state.co); @@ -2204,6 +2208,8 @@ static int get_particles_from_cache(Object *ob, ParticleSystem *psys, int cfra) /* assuming struct consists of tightly packed floats */ for(i=0, pa=psys->particles; istate.time) + copy_particle_key(&pa->prev_state,&pa->state,1); if(!BKE_ptcache_file_read_floats(pf, (float*)&pa->state, sizeof(ParticleKey)/sizeof(float))) { BKE_ptcache_file_close(pf); return 0; @@ -2489,14 +2495,12 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo Object *eob = ec->ob; ParticleSystem *epsys = BLI_findlink(&eob->particlesystem,ec->psys_nbr); ParticleSettings *epart = epsys->part; - ParticleData *epa = epsys->particles; - int totepart = epsys->totpart; + ParticleData *epa; + int p, totepart = epsys->totpart; if(psys->part->phystype==PART_PHYS_BOIDS){ - ParticleData *epa; ParticleKey state; PartDeflect *pd; - int p; pd= epart->pd; if(pd->forcefield==PFIELD_FORCE && totepart){ @@ -2512,6 +2516,7 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo BLI_kdtree_balance(tree); } } + } else if(ec->type==PSYS_EC_DEFLECT) { CollisionModifierData *collmd = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) ); @@ -2573,7 +2578,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P } else { do_physical_effector(eob, state->co, pd->forcefield,pd->f_strength,distance, falloff,0.0,pd->f_damp,eob->obmat[2],vec_to_part, - pa->state.vel,force_field,pd->flag&PFIELD_PLANAR,ec->rng,pd->f_noise,charge,pa->size); + state->vel,force_field,pd->flag&PFIELD_PLANAR,ec->rng,pd->f_noise,charge,pa->size); } } if(ec->type & PSYS_EC_PARTICLE){ @@ -2602,7 +2607,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P if(epsys==psys && p == pa_no) continue; epa = epsys->particles + p; - estate.time=-1.0; + estate.time=cfra; if(psys_get_particle_state(eob,epsys,p,&estate,0)){ VECSUB(vec_to_part, state->co, estate.co); distance = VecLength(vec_to_part); @@ -2641,7 +2646,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P /* Newtonian physics */ /************************************************/ /* gathers all forces that effect particles and calculates a new state for the particle */ -static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, float timestep, float dfra, float cfra, ParticleKey *state) +static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, float timestep, float dfra, float cfra) { ParticleKey states[5], tkey; float force[3],tvel[3],dx[4][3],dv[4][3]; @@ -2649,7 +2654,7 @@ static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, Parti int i, steps=1; /* maintain angular velocity */ - VECCOPY(state->ave,pa->state.ave); + VECCOPY(pa->state.ave,pa->prev_state.ave); if(part->flag & PART_SIZEMASS) pa_mass*=pa->size; @@ -2699,8 +2704,8 @@ static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, Parti switch(part->integrator){ case PART_INT_EULER: - VECADDFAC(state->co,states->co,states->vel,dtime); - VECADDFAC(state->vel,states->vel,force,dtime); + VECADDFAC(pa->state.co,states->co,states->vel,dtime); + VECADDFAC(pa->state.vel,states->vel,force,dtime); break; case PART_INT_MIDPOINT: if(i==0){ @@ -2709,8 +2714,8 @@ static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, Parti fra=psys->cfra+0.5f*dfra; } else{ - VECADDFAC(state->co,states->co,states[1].vel,dtime); - VECADDFAC(state->vel,states->vel,force,dtime); + VECADDFAC(pa->state.co,states->co,states[1].vel,dtime); + VECADDFAC(pa->state.vel,states->vel,force,dtime); } break; case PART_INT_RK4: @@ -2750,15 +2755,15 @@ static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, Parti VECCOPY(dv[3],force); VecMulf(dv[3],dtime); - VECADDFAC(state->co,states->co,dx[0],1.0f/6.0f); - VECADDFAC(state->co,state->co,dx[1],1.0f/3.0f); - VECADDFAC(state->co,state->co,dx[2],1.0f/3.0f); - VECADDFAC(state->co,state->co,dx[3],1.0f/6.0f); + VECADDFAC(pa->state.co,states->co,dx[0],1.0f/6.0f); + VECADDFAC(pa->state.co,pa->state.co,dx[1],1.0f/3.0f); + VECADDFAC(pa->state.co,pa->state.co,dx[2],1.0f/3.0f); + VECADDFAC(pa->state.co,pa->state.co,dx[3],1.0f/6.0f); - VECADDFAC(state->vel,states->vel,dv[0],1.0f/6.0f); - VECADDFAC(state->vel,state->vel,dv[1],1.0f/3.0f); - VECADDFAC(state->vel,state->vel,dv[2],1.0f/3.0f); - VECADDFAC(state->vel,state->vel,dv[3],1.0f/6.0f); + VECADDFAC(pa->state.vel,states->vel,dv[0],1.0f/6.0f); + VECADDFAC(pa->state.vel,pa->state.vel,dv[1],1.0f/3.0f); + VECADDFAC(pa->state.vel,pa->state.vel,dv[2],1.0f/3.0f); + VECADDFAC(pa->state.vel,pa->state.vel,dv[3],1.0f/6.0f); } break; } @@ -2766,62 +2771,62 @@ static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, Parti /* damp affects final velocity */ if(part->dampfac!=0.0) - VecMulf(state->vel,1.0f-part->dampfac); + VecMulf(pa->state.vel,1.0f-part->dampfac); /* finally we do guides */ time=(cfra-pa->time)/pa->lifetime; CLAMP(time,0.0,1.0); - VECCOPY(tkey.co,state->co); - VECCOPY(tkey.vel,state->vel); - tkey.time=state->time; + VECCOPY(tkey.co,pa->state.co); + VECCOPY(tkey.vel,pa->state.vel); + tkey.time=pa->state.time; if(part->type != PART_HAIR) { if(do_guide(&tkey,pa_no,time,&psys->effectors)) { - VECCOPY(state->co,tkey.co); + VECCOPY(pa->state.co,tkey.co); /* guides don't produce valid velocity */ - VECSUB(state->vel,tkey.co,pa->state.co); - VecMulf(state->vel,1.0f/dtime); - state->time=tkey.time; + VECSUB(pa->state.vel,tkey.co,pa->prev_state.co); + VecMulf(pa->state.vel,1.0f/dtime); + pa->state.time=tkey.time; } } } -static void rotate_particle(ParticleSettings *part, ParticleData *pa, float dfra, float timestep, ParticleKey *state) +static void rotate_particle(ParticleSettings *part, ParticleData *pa, float dfra, float timestep) { float rotfac, rot1[4], rot2[4]={1.0,0.0,0.0,0.0}, dtime=dfra*timestep; if((part->flag & PART_ROT_DYN)==0){ if(part->avemode==PART_AVE_SPIN){ float angle; - float len1 = VecLength(pa->state.vel); - float len2 = VecLength(state->vel); + float len1 = VecLength(pa->prev_state.vel); + float len2 = VecLength(pa->state.vel); if(len1==0.0f || len2==0.0f) - state->ave[0]=state->ave[1]=state->ave[2]=0.0f; + pa->state.ave[0]=pa->state.ave[1]=pa->state.ave[2]=0.0f; else{ - Crossf(state->ave,pa->state.vel,state->vel); - Normalize(state->ave); - angle=Inpf(pa->state.vel,state->vel)/(len1*len2); - VecMulf(state->ave,saacos(angle)/dtime); + Crossf(pa->state.ave,pa->prev_state.vel,pa->state.vel); + Normalize(pa->state.ave); + angle=Inpf(pa->prev_state.vel,pa->state.vel)/(len1*len2); + VecMulf(pa->state.ave,saacos(angle)/dtime); } - VecRotToQuat(state->vel,dtime*part->avefac,rot2); + VecRotToQuat(pa->state.vel,dtime*part->avefac,rot2); } } - rotfac=VecLength(state->ave); + rotfac=VecLength(pa->state.ave); if(rotfac==0.0){ /* QuatOne (in VecRotToQuat) doesn't give unit quat [1,0,0,0]?? */ rot1[0]=1.0; rot1[1]=rot1[2]=rot1[3]=0; } else{ - VecRotToQuat(state->ave,rotfac*dtime,rot1); + VecRotToQuat(pa->state.ave,rotfac*dtime,rot1); } - QuatMul(state->rot,rot1,pa->state.rot); - QuatMul(state->rot,rot2,state->rot); + QuatMul(pa->state.rot,rot1,pa->prev_state.rot); + QuatMul(pa->state.rot,rot2,pa->state.rot); /* keep rotation quat in good health */ - NormalQuat(state->rot); + NormalQuat(pa->state.rot); } /* convert from triangle barycentric weights to quad mean value weights */ @@ -3055,7 +3060,7 @@ static void particle_intersect_face(void *userdata, int index, const BVHTreeRay /* angular momentum <-> linear momentum and swept sphere - mesh collisions */ /* 1. check for all possible deflectors for closest intersection on particle path */ /* 2. if deflection was found kill the particle or calculate new coordinates */ -static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float timestep, float dfra, float cfra, ParticleKey *state){ +static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float timestep, float dfra, float cfra){ Object *ob; ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; @@ -3067,8 +3072,8 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part float radius = ((part->flag & PART_SIZE_DEFL)?pa->size:0.0f); int deflections=0, max_deflections=10; - VECCOPY(col.co1, pa->state.co); - VECCOPY(col.co2, state->co); + VECCOPY(col.co1, pa->prev_state.co); + VECCOPY(col.co2, pa->state.co); col.t = 0.0f; /* 10 iterations to catch multiple deflections */ @@ -3126,16 +3131,16 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part /* we have to add this for dying particles too so that reactors work correctly */ VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f)); - VECCOPY(state->co, co); - VecLerpf(state->vel, pa->state.vel, state->vel, dt); - QuatInterpol(state->rot, pa->state.rot, state->rot, dt); - VecLerpf(state->ave, pa->state.ave, state->ave, dt); + VECCOPY(pa->state.co, co); + VecLerpf(pa->state.vel, pa->prev_state.vel, pa->state.vel, dt); + QuatInterpol(pa->state.rot, pa->prev_state.rot, pa->state.rot, dt); + VecLerpf(pa->state.ave, pa->prev_state.ave, pa->state.ave, dt); /* particle is dead so we don't need to calculate further */ deflections=max_deflections; /* store for reactors */ - copy_particle_key(&reaction_state,state,0); + copy_particle_key(&reaction_state,&pa->state,0); if(part->flag & PART_STICKY){ pa->stick_ob=ob; @@ -3183,7 +3188,7 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part VECSUB(surface_vel, tan_vec, tan_vel); /* direction of rolling friction */ - Crossf(rot_vel, state->ave, col.nor); + Crossf(rot_vel, pa->state.ave, col.nor); /* convert to current dt */ VecMulf(rot_vel, (timestep*dfra) * (1.0f - col.t)); VecMulf(rot_vel, pa->size); @@ -3213,8 +3218,8 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part /* convert back to normal time */ VecMulf(dave, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001)); - VecMulf(state->ave, 1.0 - frict*0.01); - VECADD(state->ave, state->ave, dave); + VecMulf(pa->state.ave, 1.0 - frict*0.01); + VECADD(pa->state.ave, pa->state.ave, dave); } /* combine components together again */ @@ -3229,8 +3234,8 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part /* store state for reactors */ VECCOPY(reaction_state.co, co); - VecLerpf(reaction_state.vel, pa->state.vel, state->vel, dt); - QuatInterpol(reaction_state.rot, pa->state.rot, state->rot, dt); + VecLerpf(reaction_state.vel, pa->prev_state.vel, pa->state.vel, dt); + QuatInterpol(reaction_state.rot, pa->prev_state.rot, pa->state.rot, dt); /* set coordinates for next iteration */ VECCOPY(col.co1, co); @@ -3239,15 +3244,15 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part if(VecLength(vec) < 0.001 && VecLength(pa->state.vel) < 0.001) { /* kill speed to stop slipping */ - VECCOPY(state->vel,zerovec); - VECCOPY(state->co, co); + VECCOPY(pa->state.vel,zerovec); + VECCOPY(pa->state.co, co); if(part->flag & PART_ROT_DYN) { - VECCOPY(state->ave,zerovec); + VECCOPY(pa->state.ave,zerovec); } } else { - VECCOPY(state->co, col.co2); - VECCOPY(state->vel, vel); + VECCOPY(pa->state.co, col.co2); + VECCOPY(pa->state.vel, vel); } } deflections++; @@ -3448,18 +3453,18 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS switch(part->boidrule[i]){ case BOID_COLLIDE: /* collision avoidance */ - bvf->Copyf(dvec,pa->state.vel); + bvf->Copyf(dvec,pa->prev_state.vel); bvf->Mulf(dvec,5.0f); - bvf->Addf(dvec,dvec,pa->state.co); - if(boid_see_mesh(&psys->effectors,ob,psys,pa->state.co,dvec,ob_co,ob_nor,cfra)){ + bvf->Addf(dvec,dvec,pa->prev_state.co); + if(boid_see_mesh(&psys->effectors,ob,psys,pa->prev_state.co,dvec,ob_co,ob_nor,cfra)){ float probelen = bvf->Length(dvec); float proj; float oblen; Normalize(ob_nor); - proj = bvf->Inpf(ob_nor,pa->state.vel); + proj = bvf->Inpf(ob_nor,pa->prev_state.vel); - bvf->Subf(dvec,pa->state.co,ob_co); + bvf->Subf(dvec,pa->prev_state.co,ob_co); oblen=bvf->Length(dvec); bvf->Copyf(dvec,ob_nor); @@ -3479,7 +3484,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS if(pd->forcefield==PFIELD_FORCE && pd->f_strength<0.0){ float distance; - VECSUB(dvec,eob->obmat[3],pa->state.co); + VECSUB(dvec,eob->obmat[3],pa->prev_state.co); distance=Normalize(dvec); @@ -3514,11 +3519,11 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS totepart= epsys->totpart; if(pd->forcefield==PFIELD_FORCE && pd->f_strength<0.0 && ec->tree){ - count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->state.co,NULL,ptn2); + count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->prev_state.co,NULL,ptn2); for(p=0; pstate.co); + VECSUB(dvec, state.co, pa->prev_state.co); distance = Normalize(dvec); @@ -3549,7 +3554,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS for(n=1; nsize){ if(ptn[n].dist!=0.0f) { - bvf->Subf(dvec,pa->state.co,pars[ptn[n].index].state.co); + bvf->Subf(dvec,pa->prev_state.co,pars[ptn[n].index].state.co); bvf->Mulf(dvec,(2.0f*pa->size-ptn[n].dist)/ptn[n].dist); bvf->Addf(avoid,avoid,dvec); near++; @@ -3572,7 +3577,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS } bvf->Mulf(center,1.0f/((float)neighbours-1.0f)); - bvf->Subf(dvec,center,pa->state.co); + bvf->Subf(dvec,center,pa->prev_state.co); bvf->Mulf(dvec,part->boidfac[BOID_CENTER]*2.0f); @@ -3581,9 +3586,9 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS break; case BOID_AV_VEL: /* average velocity */ - cur_vel=bvf->Length(pa->state.vel); + cur_vel=bvf->Length(pa->prev_state.vel); if(cur_vel>0.0){ - bvf->Copyf(dvec,pa->state.vel); + bvf->Copyf(dvec,pa->prev_state.vel); bvf->Mulf(dvec,part->boidfac[BOID_AV_VEL]*(avg_vel-cur_vel)/cur_vel); not_finished=add_boid_acc(bvf,max_lat_acc,max_tan_acc,&lat_accu,&tan_accu,acc,dvec,0); } @@ -3598,7 +3603,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS } bvf->Mulf(velocity,1.0f/((float)neighbours-1.0f)); - bvf->Subf(dvec,velocity,pa->state.vel); + bvf->Subf(dvec,velocity,pa->prev_state.vel); bvf->Mulf(dvec,part->boidfac[BOID_VEL_MATCH]); @@ -3616,7 +3621,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS if(pd->forcefield==PFIELD_FORCE && pd->f_strength>0.0){ float distance; - VECSUB(dvec,eob->obmat[3],pa->state.co); + VECSUB(dvec,eob->obmat[3],pa->prev_state.co); distance=Normalize(dvec); @@ -3633,7 +3638,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS where_on_path(eob, (cfra-pa->time)/pa->lifetime, temp, dvec); - VECSUB(dvec,temp,pa->state.co); + VECSUB(dvec,temp,pa->prev_state.co); distance=Normalize(dvec); @@ -3661,11 +3666,11 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS totepart= epsys->totpart; if(pd->forcefield==PFIELD_FORCE && pd->f_strength>0.0 && ec->tree){ - count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->state.co,NULL,ptn2); + count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->prev_state.co,NULL,ptn2); for(p=0; pstate.co); + VECSUB(dvec, state.co, pa->prev_state.co); distance = Normalize(dvec); @@ -3687,7 +3692,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS /* level flight */ if((part->flag & PART_BOIDS_2D)==0){ dvec[0]=dvec[1]=0.0; - dvec[2]=-pa->state.vel[2]; + dvec[2]=-pa->prev_state.vel[2]; VecMulf(dvec,part->boidfac[BOID_LEVEL]); not_finished=add_boid_acc(bvf,max_lat_acc,max_tan_acc,&lat_accu,&tan_accu,acc,dvec,0); @@ -3697,7 +3702,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS } } /* tries to realize the wanted acceleration */ -static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, ParticleSettings *part, float timestep, float *acc, ParticleKey *state) +static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, ParticleSettings *part, float timestep, float *acc) { float dvec[3], bvec[3], length, max_vel=part->max_vel; float q2[4], q[4]; @@ -3705,7 +3710,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, float yvec[3]={0.0,1.0,0.0}, zvec[3]={0.0,0.0,-1.0}, bank; /* apply new velocity, location & rotation */ - copy_particle_key(state,&pa->state,0); + copy_particle_key(&pa->state,&pa->prev_state,0); if(part->flag & PART_SIZEMASS) pa_mass*=pa->size; @@ -3717,10 +3722,10 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, bvf->Copyf(dvec,acc); bvf->Mulf(dvec,timestep*timestep*0.5f); - bvf->Copyf(bvec,state->vel); + bvf->Copyf(bvec,pa->state.vel); bvf->Mulf(bvec,timestep); bvf->Addf(dvec,dvec,bvec); - bvf->Addf(state->co,state->co,dvec); + bvf->Addf(pa->state.co,pa->state.co,dvec); /* air speed from wind and vortex effectors */ if(psys->effectors.first) { @@ -3734,7 +3739,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, if(pd->f_strength != 0.0f) { VecCopyf(direction, eob->obmat[2]); - VecSubf(vec_to_part, state->co, eob->obmat[3]); + VecSubf(vec_to_part, pa->state.co, eob->obmat[3]); falloff=effector_falloff(pd, direction, vec_to_part); @@ -3745,7 +3750,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, else { Normalize(direction); VecMulf(direction, pd->f_strength * falloff); - bvf->Addf(state->co, state->co, direction); + bvf->Addf(pa->state.co, pa->state.co, direction); } break; case PFIELD_VORTEX: @@ -3757,7 +3762,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, distance = VecLength(vec_to_part); VecMulf(mag_vec, pd->f_strength * distance * falloff); - bvf->Addf(state->co, state->co, mag_vec); + bvf->Addf(pa->state.co, pa->state.co, mag_vec); break; } } @@ -3767,8 +3772,8 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, } - if((part->flag & PART_BOIDS_2D)==0 && pa->state.vel[0]!=0.0 && pa->state.vel[0]!=0.0 && pa->state.vel[0]!=0.0){ - Crossf(yvec,state->vel,zvec); + if((part->flag & PART_BOIDS_2D)==0 && pa->prev_state.vel[0]!=0.0 && pa->prev_state.vel[0]!=0.0 && pa->prev_state.vel[0]!=0.0){ + Crossf(yvec,pa->state.vel,zvec); Normalize(yvec); @@ -3795,27 +3800,27 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, } - VecRotToQuat(state->vel,bank,q); + VecRotToQuat(pa->state.vel,bank,q); - VECCOPY(dvec,state->vel); + VECCOPY(dvec,pa->state.vel); VecMulf(dvec,-1.0f); vectoquat(dvec, OB_POSX, OB_POSZ, q2); - QuatMul(state->rot,q,q2); + QuatMul(pa->state.rot,q,q2); bvf->Mulf(acc,timestep); - bvf->Addf(state->vel,state->vel,acc); + bvf->Addf(pa->state.vel,pa->state.vel,acc); if(part->flag & PART_BOIDS_2D){ - state->vel[2]=0.0; - state->co[2]=part->groundz; + pa->state.vel[2]=0.0; + pa->state.co[2]=part->groundz; if(psys->keyed_ob && (psys->keyed_ob->type == OB_MESH)){ Object *zob=psys->keyed_ob; int min_face; float co1[3],co2[3],min_d=2.0,min_w[4],imat[4][4]; - VECCOPY(co1,state->co); - VECCOPY(co2,state->co); + VECCOPY(co1,pa->state.co); + VECCOPY(co2,pa->state.co); co1[2]=1000.0f; co2[2]=-1000.0f; @@ -3846,7 +3851,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, Normalize(nor); - VECCOPY(state->co,loc); + VECCOPY(pa->state.co,loc); zvec[2]=1.0; @@ -3858,17 +3863,17 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, VecRotToQuat(loc,bank,q); - QUATCOPY(q1,state->rot); + QUATCOPY(q1,pa->state.rot); - QuatMul(state->rot,q,q1); + QuatMul(pa->state.rot,q,q1); } } } } - length=bvf->Length(state->vel); + length=bvf->Length(pa->state.vel); if(length > max_vel) - bvf->Mulf(state->vel,max_vel/length); + bvf->Mulf(pa->state.vel,max_vel/length); } /************************************************/ /* Hair */ @@ -3925,7 +3930,6 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi float *vg_vel, float *vg_tan, float *vg_rot, float *vg_size) { ParticleData *pa; - ParticleKey *outstate, *key; ParticleSettings *part=psys->part; KDTree *tree=0; BoidVecFunc bvf; @@ -3995,15 +3999,9 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi if(vg_size) MEM_freeN(vg_size); - - //if(part->phystype==PART_PHYS_SOLID) - // reset_to_first_fragment(psys); } else{ BLI_srandom(31415926 + (int)cfra + psys->seed); - - /* outstate is used so that particles are updated in parallel */ - outstate=MEM_callocN(totpart*sizeof(ParticleKey),"Particle Outstates"); /* update effectors */ if(psys->effectors.first) @@ -4028,10 +4026,10 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi } /* main loop: calculate physics for all particles */ - for(p=0, pa=psys->particles, key=outstate; pparticles; pflag & PARS_UNEXIST) continue; - copy_particle_key(key,&pa->state,1); + copy_particle_key(&pa->prev_state,&pa->state,1); /* set correct ipo timing */ if((part->flag&PART_ABS_TIME)==0 && part->ipo){ @@ -4041,7 +4039,12 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi } pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); + /* reactions can change birth time so they need to be checked first */ + if(psys->reactevents.first && ELEM(pa->alive,PARS_DEAD,PARS_KILLED)==0) + react_to_events(psys,p); + birthtime = pa->time + pa->loop * pa->lifetime; + dietime = birthtime + pa->lifetime; /* allways reset particles to emitter before birth */ if(pa->alive==PARS_UNBORN @@ -4049,91 +4052,72 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED) || birthtime >= cfra){ reset_particle(pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); - copy_particle_key(key,&pa->state,1); } - if(1) { - - if(psys->reactevents.first && ELEM(pa->alive,PARS_DEAD,PARS_KILLED)==0) - react_to_events(psys,p); + pa_dfra = dfra; + pa_dtime = dtime; - pa_dfra = dfra; - pa_dtime = dtime; - - /* we need to calculate this once again because reactions might have changed pa->time */ - birthtime = pa->time + pa->loop * pa->lifetime; - dietime = birthtime + pa->lifetime; - - if(birthtime <= cfra && birthtime >= psys->cfra){ - /* particle is born some time between this and last step*/ - pa->alive = PARS_ALIVE; - pa_dfra = cfra - birthtime; - pa_dtime = pa_dfra*timestep; - } - else if(dietime <= cfra && psys->cfra < dietime){ - /* particle dies some time between this and last step */ - pa_dfra = dietime - psys->cfra; - pa_dtime = pa_dfra * timestep; - pa->alive = PARS_DYING; - } - else if(dietime < cfra){ - /* nothing to be done when particle is dead */ - } + if(birthtime <= cfra && birthtime >= psys->cfra){ + /* particle is born some time between this and last step*/ + pa->alive = PARS_ALIVE; + pa_dfra = cfra - birthtime; + pa_dtime = pa_dfra*timestep; + } + else if(dietime <= cfra && psys->cfra < dietime){ + /* particle dies some time between this and last step */ + pa_dfra = dietime - psys->cfra; + pa_dtime = pa_dfra * timestep; + pa->alive = PARS_DYING; + } + else if(dietime < cfra){ + /* nothing to be done when particle is dead */ + } - copy_particle_key(key,&pa->state,1); - if(dfra>0.0 && ELEM(pa->alive,PARS_ALIVE,PARS_DYING)){ - switch(part->phystype){ - case PART_PHYS_NEWTON: - /* do global forces & effectors */ - apply_particle_forces(p,pa,ob,psys,part,timestep,pa_dfra,cfra,key); - - /* deflection */ - deflect_particle(ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra,key); + if(dfra>0.0 && ELEM(pa->alive,PARS_ALIVE,PARS_DYING)){ + switch(part->phystype){ + case PART_PHYS_NEWTON: + /* do global forces & effectors */ + apply_particle_forces(p,pa,ob,psys,part,timestep,pa_dfra,cfra); + + /* deflection */ + deflect_particle(ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra); - /* rotations */ - rotate_particle(part,pa,pa_dfra,timestep,key); - break; - case PART_PHYS_BOIDS: - { - float acc[3]; - boid_brain(&bvf,pa,ob,psys,part,tree,timestep,cfra,acc); - if(pa->alive != PARS_DYING) - boid_body(&bvf,pa,psys,part,timestep,acc,key); - break; - } + /* rotations */ + rotate_particle(part,pa,pa_dfra,timestep); + break; + case PART_PHYS_BOIDS: + { + float acc[3]; + boid_brain(&bvf,pa,ob,psys,part,tree,timestep,cfra,acc); + if(pa->alive != PARS_DYING) + boid_body(&bvf,pa,psys,part,timestep,acc); + break; } + } - if(pa->alive == PARS_DYING){ - push_reaction(ob,psys,p,PART_EVENT_DEATH,key); - - if(part->flag & PART_LOOP && part->type!=PART_HAIR){ - pa->loop++; - reset_particle(pa,psys,psmd,ob,0.0,cfra,vg_vel,vg_tan,vg_rot); - copy_particle_key(key,&pa->state,1); - pa->alive=PARS_ALIVE; - } - else{ - pa->alive=PARS_DEAD; - key->time=pa->dietime; + if(pa->alive == PARS_DYING){ + push_reaction(ob,psys,p,PART_EVENT_DEATH,&pa->state); - if(pa->flag&PARS_STICKY) - psys_key_to_object(pa->stick_ob,key,0); - } + if(part->flag & PART_LOOP && part->type!=PART_HAIR){ + pa->loop++; + reset_particle(pa,psys,psmd,ob,0.0,cfra,vg_vel,vg_tan,vg_rot); + pa->alive=PARS_ALIVE; } - else - key->time=cfra; + else{ + pa->alive=PARS_DEAD; + pa->state.time=pa->dietime; - push_reaction(ob,psys,p,PART_EVENT_NEAR,key); + if(pa->flag&PARS_STICKY) + psys_key_to_object(pa->stick_ob,&pa->state,0); + } } + else + pa->state.time=cfra; + + push_reaction(ob,psys,p,PART_EVENT_NEAR,&pa->state); } } - - /* apply outstates to particles */ - for(p=0, pa=psys->particles, key=outstate; pstate,key,1); - - MEM_freeN(outstate); } if(psys->reactevents.first) BLI_freelistN(&psys->reactevents); diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 8618bee3638..7dd69b2151c 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -66,6 +66,8 @@ typedef struct ParticleData { ParticleKey state; /* normally current global coordinates or */ /* in sticky object space if dead & sticky */ + ParticleKey prev_state; /* previous state */ + HairKey *hair; /* hair vertices */ ParticleKey *keys; /* keyed states */ -- cgit v1.2.3 From d72d4a505824b59447e84cd27a692d786c452978 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 23 Sep 2008 13:35:32 +0000 Subject: fix for [#11744] NurbCurve Radius incorrect removed calc_curve_subdiv_radius(), curve radius is now calculated the same way as tilt. Added radius interpolation menu matching tilt interpolation, needed to add "Ease" interpolation type to keep 2.47 curves looking the same. --- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/BKE_curve.h | 5 +- source/blender/blenkernel/intern/curve.c | 359 ++++++++++++---------------- source/blender/blenkernel/intern/displist.c | 6 +- source/blender/blenkernel/intern/particle.c | 1 - source/blender/blenloader/intern/readfile.c | 14 ++ source/blender/makesdna/DNA_curve_types.h | 4 +- source/blender/src/buttons_editing.c | 19 +- source/blender/src/drawobject.c | 14 +- 9 files changed, 190 insertions(+), 234 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 268cf34fb64..f123c14fddf 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -41,7 +41,7 @@ struct ListBase; struct MemFile; #define BLENDER_VERSION 247 -#define BLENDER_SUBVERSION 5 +#define BLENDER_SUBVERSION 6 #define BLENDER_MINVERSION 245 #define BLENDER_MINSUBVERSION 15 diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 006e3ac1e79..25d6d78c4aa 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -65,15 +65,14 @@ void minmaxNurb( struct Nurb *nu, float *min, float *max); void makeknots( struct Nurb *nu, short uv, short type); -void makeNurbfaces( struct Nurb *nu, float *data, int rowstride); -void makeNurbcurve( struct Nurb *nu, float *data, int resolu, int dim); +void makeNurbfaces(struct Nurb *nu, float *coord_array, int rowstride); +void makeNurbcurve(struct Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, int resolu); void forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride); float *make_orco_curve( struct Object *ob); float *make_orco_surf( struct Object *ob); void makebevelcurve( struct Object *ob, struct ListBase *disp); void makeBevelList( struct Object *ob); -float calc_curve_subdiv_radius( struct Curve *cu, struct Nurb *nu, int cursubdiv); void calchandleNurb( struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next, int mode); void calchandlesNurb( struct Nurb *nu); diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 49d25b0652d..c12fe920594 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -247,7 +247,7 @@ void tex_space_curve(Curve *cu) { DispList *dl; BoundBox *bb; - float *data, min[3], max[3], loc[3], size[3]; + float *fp, min[3], max[3], loc[3], size[3]; int tot, doit= 0; if(cu->bb==NULL) cu->bb= MEM_callocN(sizeof(BoundBox), "boundbox"); @@ -262,10 +262,10 @@ void tex_space_curve(Curve *cu) else tot= dl->nr*dl->parts; if(tot) doit= 1; - data= dl->verts; + fp= dl->verts; while(tot--) { - DO_MINMAX(data, min, max); - data+= 3; + DO_MINMAX(fp, min, max); + fp += 3; } dl= dl->next; } @@ -650,8 +650,8 @@ static void basisNurb(float t, short order, short pnts, float *knots, float *bas } -void makeNurbfaces(Nurb *nu, float *data, int rowstride) -/* data has to be 3*4*resolu*resolv in size, and zero-ed */ +void makeNurbfaces(Nurb *nu, float *coord_array, int rowstride) +/* coord_array has to be 3*4*resolu*resolv in size, and zero-ed */ { BPoint *bp; float *basisu, *basis, *basisv, *sum, *fp, *in; @@ -662,7 +662,7 @@ void makeNurbfaces(Nurb *nu, float *data, int rowstride) if(nu->knotsu==NULL || nu->knotsv==NULL) return; if(nu->orderu>nu->pntsu) return; if(nu->orderv>nu->pntsv) return; - if(data==0) return; + if(coord_array==NULL) return; /* allocate and initialize */ len= nu->pntsu*nu->pntsv; @@ -722,7 +722,7 @@ void makeNurbfaces(Nurb *nu, float *data, int rowstride) if(nu->flagu & CU_CYCLIC) cycl= nu->orderu-1; else cycl= 0; - in= data; + in= coord_array; u= ustart; while(resolu--) { @@ -809,17 +809,19 @@ void makeNurbfaces(Nurb *nu, float *data, int rowstride) MEM_freeN(jend); } -void makeNurbcurve(Nurb *nu, float *data, int resolu, int dim) -/* data has to be dim*4*pntsu*resolu in size and zero-ed */ +void makeNurbcurve(Nurb *nu, float *coord_array, float *tilt_array, float *radius_array, int resolu) +/* coord_array has to be 3*4*pntsu*resolu in size and zero-ed + * tilt_array and radius_array will be written to if valid */ { BPoint *bp; float u, ustart, uend, ustep, sumdiv; - float *basisu, *sum, *fp, *in; + float *basisu, *sum, *fp; + float *coord_fp= coord_array, *tilt_fp= tilt_array, *radius_fp= radius_array; int i, len, istart, iend, cycl; if(nu->knotsu==NULL) return; if(nu->orderu>nu->pntsu) return; - if(data==0) return; + if(coord_array==0) return; /* allocate and initialize */ len= nu->pntsu; @@ -842,7 +844,6 @@ void makeNurbcurve(Nurb *nu, float *data, int resolu, int dim) if(nu->flagu & CU_CYCLIC) cycl= nu->orderu-1; else cycl= 0; - in= data; u= ustart; while(resolu--) { @@ -877,17 +878,24 @@ void makeNurbcurve(Nurb *nu, float *data, int resolu, int dim) if(*fp!=0.0) { - in[0]+= (*fp) * bp->vec[0]; - in[1]+= (*fp) * bp->vec[1]; - if(dim>=3) { - in[2]+= (*fp) * bp->vec[2]; - if(dim==4) in[3]+= (*fp) * bp->alfa; - } + coord_fp[0]+= (*fp) * bp->vec[0]; + coord_fp[1]+= (*fp) * bp->vec[1]; + coord_fp[2]+= (*fp) * bp->vec[2]; + + if (tilt_fp) + (*tilt_fp) += (*fp) * bp->alfa; + + if (radius_fp) + (*radius_fp) += (*fp) * bp->radius; + } } - in+= dim; - + coord_fp+= 3; + + if (tilt_fp) tilt_fp++; + if (radius_fp) radius_fp++; + u+= ustep; } @@ -932,7 +940,7 @@ float *make_orco_surf(Object *ob) Nurb *nu; int a, b, tot=0; int sizeu, sizev; - float *data, *orco; + float *fp, *coord_array; /* first calculate the size of the datablock */ nu= cu->nurb.first; @@ -955,7 +963,7 @@ float *make_orco_surf(Object *ob) nu= nu->next; } /* makeNurbfaces wants zeros */ - data= orco= MEM_callocN(3*sizeof(float)*tot, "make_orco"); + fp= coord_array= MEM_callocN(3*sizeof(float)*tot, "make_orco"); nu= cu->nurb.first; while(nu) { @@ -969,15 +977,15 @@ float *make_orco_surf(Object *ob) for(b=0; b< sizeu; b++) { for(a=0; a< sizev; a++) { - if(sizev <2) data[0]= 0.0f; - else data[0]= -1.0f + 2.0f*((float)a)/(sizev - 1); + if(sizev <2) fp[0]= 0.0f; + else fp[0]= -1.0f + 2.0f*((float)a)/(sizev - 1); - if(sizeu <2) data[1]= 0.0f; - else data[1]= -1.0f + 2.0f*((float)b)/(sizeu - 1); + if(sizeu <2) fp[1]= 0.0f; + else fp[1]= -1.0f + 2.0f*((float)b)/(sizeu - 1); - data[2]= 0.0; + fp[2]= 0.0; - data+= 3; + fp+= 3; } } } @@ -999,10 +1007,10 @@ float *make_orco_surf(Object *ob) tdata = _tdata + 3 * (use_b * nu->resolv + use_a); - data[0]= (tdata[0]-cu->loc[0])/cu->size[0]; - data[1]= (tdata[1]-cu->loc[1])/cu->size[1]; - data[2]= (tdata[2]-cu->loc[2])/cu->size[2]; - data+= 3; + fp[0]= (tdata[0]-cu->loc[0])/cu->size[0]; + fp[1]= (tdata[1]-cu->loc[1])/cu->size[1]; + fp[2]= (tdata[2]-cu->loc[2])/cu->size[2]; + fp+= 3; } } @@ -1012,7 +1020,7 @@ float *make_orco_surf(Object *ob) nu= nu->next; } - return orco; + return coord_array; } @@ -1024,7 +1032,7 @@ float *make_orco_curve(Object *ob) Curve *cu = ob->data; DispList *dl; int u, v, numVerts; - float *fp, *orco; + float *fp, *coord_array; int remakeDisp = 0; if (!(cu->flag&CU_UV_ORCO) && cu->key && cu->key->refkey) { @@ -1052,7 +1060,7 @@ float *make_orco_curve(Object *ob) } } - fp= orco= MEM_mallocN(3*sizeof(float)*numVerts, "cu_orco"); + fp= coord_array= MEM_mallocN(3*sizeof(float)*numVerts, "cu_orco"); for (dl=cu->disp.first; dl; dl=dl->next) { if (dl->type==DL_INDEX3) { for (u=0; unr; u++, fp+=3) { @@ -1102,7 +1110,7 @@ float *make_orco_curve(Object *ob) makeDispListCurveTypes(ob, 0); } - return orco; + return coord_array; } @@ -1429,7 +1437,7 @@ static void calc_bevel_sin_cos(float x1, float y1, float x2, float y2, float *si } -static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *data_a, int resolu) +static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float *tilt_array, float *radius_array, int resolu) { BezTriple *pprev, *next, *last; float fac, dfac, t[4]; @@ -1455,10 +1463,30 @@ static void alfa_bezpart(BezTriple *prevbezt, BezTriple *bezt, Nurb *nu, float * dfac= 1.0f/(float)resolu; for(a=0; atilt_interp==3) { /* May as well support for tilt also 2.47 ease interp */ + tilt_array[a] = prevbezt->alfa + (bezt->alfa - prevbezt->alfa)*(3.0f*fac*fac - 2.0f*fac*fac*fac); + } else { + set_four_ipo(fac, t, nu->tilt_interp); + tilt_array[a]= t[0]*pprev->alfa + t[1]*prevbezt->alfa + t[2]*bezt->alfa + t[3]*next->alfa; + } + } - set_four_ipo(fac, t, nu->tilt_interp); - - data_a[a]= t[0]*pprev->alfa + t[1]*prevbezt->alfa + t[2]*bezt->alfa + t[3]*next->alfa; + if (radius_array) { + if (nu->radius_interp==3) { + /* Support 2.47 ease interp + * Note! - this only takes the 2 points into account, + * giving much more localized results to changes in radius, sometimes you want that */ + radius_array[a] = prevbezt->radius + (bezt->radius - prevbezt->radius)*(3.0f*fac*fac - 2.0f*fac*fac*fac); + } else { + + /* reuse interpolation from tilt if we can */ + if (tilt_array==NULL || nu->tilt_interp != nu->radius_interp) { + set_four_ipo(fac, t, nu->radius_interp); + } + radius_array[a]= t[0]*pprev->radius + t[1]*prevbezt->radius + t[2]*bezt->radius + t[3]*next->radius; + } + } } } @@ -1476,13 +1504,19 @@ void makeBevelList(Object *ob) BPoint *bp; BevList *bl, *blnew, *blnext; BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0; - float *data, *data_a, *v1, *v2, min, inp, x1, x2, y1, y2, vec[3]; + float min, inp, x1, x2, y1, y2, vec[3]; + float *coord_array, *tilt_array=NULL, *radius_array=NULL, *coord_fp, *tilt_fp=NULL, *radius_fp; + float *v1, *v2; struct bevelsort *sortdata, *sd, *sd1; int a, b, nr, poly, resolu, len=0; - + int do_tilt, do_radius; + /* this function needs an object, because of tflag and upflag */ cu= ob->data; + /* do we need to calculate the radius for each point? */ + do_radius = (cu->bevobj || cu->taperobj || (cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ? 0 : 1; + /* STEP 1: MAKE POLYS */ BLI_freelistN(&(cu->bev)); @@ -1490,10 +1524,14 @@ void makeBevelList(Object *ob) else nu= cu->nurb.first; while(nu) { + + /* check if we will calculate tilt data */ + do_tilt = ((nu->type & CU_2D) && (cu->flag & CU_3D)==0) ? 0 : 1; + /* check we are a single point? also check we are not a surface and that the orderu is sane, * enforced in the UI but can go wrong possibly */ if(!check_valid_nurb_u(nu)) { - bl= MEM_callocN(sizeof(BevList)+1*sizeof(BevPoint), "makeBevelList"); + bl= MEM_callocN(sizeof(BevList)+1*sizeof(BevPoint), "makeBevelList1"); BLI_addtail(&(cu->bev), bl); bl->nr= 0; } else { @@ -1504,7 +1542,7 @@ void makeBevelList(Object *ob) if((nu->type & 7)==CU_POLY) { len= nu->pntsu; - bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList"); + bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList2"); BLI_addtail(&(cu->bev), bl); if(nu->flagu & CU_CYCLIC) bl->poly= 0; @@ -1519,6 +1557,7 @@ void makeBevelList(Object *ob) bevp->y= bp->vec[1]; bevp->z= bp->vec[2]; bevp->alfa= bp->alfa; + bevp->radius= bp->radius; bevp->f1= SELECT; bevp++; bp++; @@ -1527,7 +1566,7 @@ void makeBevelList(Object *ob) else if((nu->type & 7)==CU_BEZIER) { len= resolu*(nu->pntsu+ (nu->flagu & CU_CYCLIC) -1)+1; /* in case last point is not cyclic */ - bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList"); + bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelBPoints"); BLI_addtail(&(cu->bev), bl); if(nu->flagu & CU_CYCLIC) bl->poly= 0; @@ -1545,8 +1584,13 @@ void makeBevelList(Object *ob) bezt++; } - data= MEM_mallocN(3*sizeof(float)*(resolu+1), "makeBevelList2"); - data_a= MEM_callocN(sizeof(float)*(resolu+1), "data_a"); + coord_array= coord_fp= MEM_mallocN(3*sizeof(float)*(resolu+1), "makeBevelCoords"); + + if(do_tilt) + tilt_array= tilt_fp= MEM_callocN(sizeof(float)*(resolu+1), "makeBevelTilt"); + + if (do_radius) + radius_array= radius_fp= MEM_callocN(sizeof(float)*(resolu+1), "nakeBevelRadius"); while(a--) { if(prevbezt->h2==HD_VECT && bezt->h1==HD_VECT) { @@ -1555,6 +1599,7 @@ void makeBevelList(Object *ob) bevp->y= prevbezt->vec[1][1]; bevp->z= prevbezt->vec[1][2]; bevp->alfa= prevbezt->alfa; + bevp->radius= prevbezt->radius; bevp->f1= SELECT; bevp->f2= 0; bevp++; @@ -1566,16 +1611,12 @@ void makeBevelList(Object *ob) v2= bezt->vec[0]; /* always do all three, to prevent data hanging around */ - forward_diff_bezier(v1[0], v1[3], v2[0], v2[3], data, resolu, 3); - forward_diff_bezier(v1[1], v1[4], v2[1], v2[4], data+1, resolu, 3); - forward_diff_bezier(v1[2], v1[5], v2[2], v2[5], data+2, resolu, 3); - - if((nu->type & CU_2D)==0) { - if(cu->flag & CU_3D) { - alfa_bezpart(prevbezt, bezt, nu, data_a, resolu); - } - } + forward_diff_bezier(v1[0], v1[3], v2[0], v2[3], coord_array, resolu, 3); + forward_diff_bezier(v1[1], v1[4], v2[1], v2[4], coord_array+1, resolu, 3); + forward_diff_bezier(v1[2], v1[5], v2[2], v2[5], coord_array+2, resolu, 3); + if (do_tilt || do_radius) + alfa_bezpart(prevbezt, bezt, nu, tilt_array, radius_array, resolu); /* indicate with handlecodes double points */ if(prevbezt->h1==prevbezt->h2) { @@ -1586,18 +1627,28 @@ void makeBevelList(Object *ob) else if(prevbezt->h2==0 || prevbezt->h2==HD_VECT) bevp->f1= SELECT; } - v1= data; - v2= data_a; nr= resolu; + coord_fp = coord_array; + tilt_fp = tilt_array; + radius_fp = radius_array; + while(nr--) { - bevp->x= v1[0]; - bevp->y= v1[1]; - bevp->z= v1[2]; - bevp->alfa= v2[0]; + bevp->x= coord_fp[0]; + bevp->y= coord_fp[1]; + bevp->z= coord_fp[2]; + coord_fp+=3; + + if (do_tilt) { + bevp->alfa= *tilt_fp; + tilt_fp++; + } + + if (do_radius) { + bevp->radius= *radius_fp; + radius_fp++; + } bevp++; - v1+=3; - v2++; } bl->nr+= resolu; @@ -1606,17 +1657,19 @@ void makeBevelList(Object *ob) bezt++; } - MEM_freeN(data); - MEM_freeN(data_a); + MEM_freeN(coord_array); + if (do_tilt) MEM_freeN(tilt_array); + if (do_radius) MEM_freeN(radius_array); + coord_array = tilt_array = radius_array = NULL; if((nu->flagu & CU_CYCLIC)==0) { /* not cyclic: endpoint */ bevp->x= prevbezt->vec[1][0]; bevp->y= prevbezt->vec[1][1]; bevp->z= prevbezt->vec[1][2]; bevp->alfa= prevbezt->alfa; + bevp->radius= prevbezt->radius; bl->nr++; } - } else if((nu->type & 7)==CU_NURBS) { if(nu->pntsv==1) { @@ -1629,21 +1682,40 @@ void makeBevelList(Object *ob) else bl->poly= -1; bevp= (BevPoint *)(bl+1); - data= MEM_callocN(4*sizeof(float)*len, "makeBevelList4"); /* has to be zero-ed */ - makeNurbcurve(nu, data, resolu, 4); + coord_array= coord_fp= MEM_callocN(3*sizeof(float)*len, "makeBevelCoords"); /* has to be zero-ed */ + + if(do_tilt) + tilt_array= tilt_fp= MEM_callocN(sizeof(float)*len, "makeBevelTilt"); + + if (do_radius) + radius_array= radius_fp= MEM_callocN(sizeof(float)*len, "nakeBevelRadius"); + + makeNurbcurve(nu, coord_array, tilt_array, radius_array, resolu); - v1= data; while(len--) { - bevp->x= v1[0]; - bevp->y= v1[1]; - bevp->z= v1[2]; - bevp->alfa= v1[3]; + bevp->x= coord_fp[0]; + bevp->y= coord_fp[1]; + bevp->z= coord_fp[2]; + coord_fp+=3; + + if (do_tilt) { + bevp->alfa= *tilt_fp; + tilt_fp++; + } + + if (do_radius) { + bevp->radius= *radius_fp; + radius_fp++; + } + bevp->f1= bevp->f2= 0; bevp++; - v1+=4; } - MEM_freeN(data); + MEM_freeN(coord_array); + if (do_tilt) MEM_freeN(tilt_array); + if (do_radius) MEM_freeN(radius_array); + coord_array = tilt_array = radius_array = NULL; } } } @@ -1678,7 +1750,7 @@ void makeBevelList(Object *ob) blnext= bl->next; if(bl->nr && bl->flag) { nr= bl->nr- bl->flag+1; /* +1 because vectorbezier sets flag too */ - blnew= MEM_mallocN(sizeof(BevList)+nr*sizeof(BevPoint), "makeBevelList"); + blnew= MEM_mallocN(sizeof(BevList)+nr*sizeof(BevPoint), "makeBevelList4"); memcpy(blnew, bl, sizeof(BevList)); blnew->nr= 0; BLI_remlink(&(cu->bev), bl); @@ -1886,137 +1958,6 @@ void makeBevelList(Object *ob) } } -/* calculates a bevel width (radius) for a particular subdivided curve part, - * based on the radius value of the surrounding CVs */ -float calc_curve_subdiv_radius(Curve *cu, Nurb *nu, int cursubdiv) -{ - BezTriple *bezt, *beztfirst, *beztlast, *beztnext, *beztprev; - BPoint *bp, *bpfirst, *bplast; - int resolu; - float prevrad=0.0, nextrad=0.0, rad=0.0, ratio=0.0; - int vectseg=0, subdivs=0; - - if((nu==NULL) || (nu->pntsu<=1)) return 1.0; - bezt= nu->bezt; - bp = nu->bp; - - if(G.rendering && cu->resolu_ren!=0) resolu= cu->resolu_ren; - else resolu= nu->resolu; - - if(((nu->type & 7)==CU_BEZIER) && (bezt != NULL)) { - beztfirst = nu->bezt; - beztlast = nu->bezt + (nu->pntsu - 1); - - /* loop through the CVs to end up with a pointer to the CV before the subdiv in question, and a ratio - * of how far that subdiv is between this CV and the next */ - while(bezt<=beztlast) { - beztnext = bezt+1; - beztprev = bezt-1; - vectseg=0; - - if (subdivs==cursubdiv) { - ratio= 0.0; - break; - } - - /* check to see if we're looking at a vector segment (no subdivisions) */ - if (nu->flagu & CU_CYCLIC) { - if (bezt == beztfirst) { - if ((beztlast->h2==HD_VECT) && (bezt->h1==HD_VECT)) vectseg = 1; - } else { - if ((beztprev->h2==HD_VECT) && (bezt->h1==HD_VECT)) vectseg = 1; - } - } else if ((bezt->h2==HD_VECT) && (beztnext->h1==HD_VECT)) vectseg = 1; - - - if (vectseg==0) { - /* if it's NOT a vector segment, check to see if the subdiv falls within the segment */ - subdivs += resolu; - - if (cursubdiv < subdivs) { - ratio = 1.0 - ((subdivs - cursubdiv)/(float)resolu); - break; - } - } else { - /* must be a vector segment.. loop again! */ - subdivs += 1; - } - - bezt++; - } - - /* Now we have a nice bezt pointer to the CV that we want. But cyclic messes it up, so must correct for that.. - * (cyclic goes last-> first -> first+1 -> first+2 -> ...) */ - if (nu->flagu & CU_CYCLIC) { - if (bezt == beztfirst) bezt = beztlast; - else bezt--; - } - - /* find the radii at the bounding CVs and interpolate between them based on ratio */ - rad = prevrad = bezt->radius; - - if ((bezt == beztlast) && (nu->flagu & CU_CYCLIC)) { /* loop around */ - bezt= beztfirst; - } else if (bezt != beztlast) { - bezt++; - } - nextrad = bezt->radius; - - } - else if( ( ((nu->type & 7)==CU_NURBS) || ((nu->type & 7)==CU_POLY)) && (bp != NULL)) { - /* follows similar algo as for bezt above */ - bpfirst = nu->bp; - bplast = nu->bp + (nu->pntsu - 1); - - if ((nu->type & 7)==CU_POLY) resolu=1; - - while(bp<=bplast) { - if (subdivs==cursubdiv) { - ratio= 0.0; - break; - } - - subdivs += resolu; - - if (cursubdiv < subdivs) { - ratio = 1.0 - ((subdivs - cursubdiv)/(float)resolu); - break; - } - - bp++; - } - - if ( ((nu->type & 7)==CU_NURBS) && (nu->flagu & CU_CYCLIC)) { - if (bp >= bplast) bp = bpfirst; - else bp++; - } else if ( bp > bplast ) { - /* this can happen in rare cases, refer to bug [#8596] */ - bp = bplast; - } - - rad = prevrad = bp->radius; - - if ((bp == bplast) && (nu->flagu & CU_CYCLIC)) { /* loop around */ - bp= bpfirst; - } else if (bp < bplast) { - bp++; - } - nextrad = bp->radius; - - } - - - if (nextrad != prevrad) { - /* smooth interpolation */ - rad = prevrad + (nextrad-prevrad)*(3.0f*ratio*ratio - 2.0f*ratio*ratio*ratio); - } - - if (rad > 0.0) - return rad; - else - return 1.0; -} - /* ****************** HANDLES ************** */ /* diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index e55006b6c1c..598973d6974 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -871,7 +871,7 @@ static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase) data= dl->verts; if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY; else dl->type= DL_SEGM; - makeNurbcurve(nu, data, resolu, 3); + makeNurbcurve(nu, data, NULL, NULL, resolu); } else if((nu->type & 7)==CU_POLY) { len= nu->pntsu; @@ -1339,7 +1339,7 @@ void makeDispListSurf(Object *ob, ListBase *dispbase, int forRender) if(nu->flagu & CU_CYCLIC) dl->type= DL_POLY; else dl->type= DL_SEGM; - makeNurbcurve(nu, data, nu->resolu, 3); + makeNurbcurve(nu, data, NULL, NULL, nu->resolu); } else { len= nu->resolu*nu->resolv; @@ -1486,7 +1486,7 @@ void makeDispListCurveTypes(Object *ob, int forOrco) float fac=1.0; if (cu->taperobj==NULL) { if ( (cu->bevobj!=NULL) || !((cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ) - fac = calc_curve_subdiv_radius(cu, nu, a); + fac = bevp->radius; } else { fac = calc_taper(cu->taperobj, a, bl->nr); } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 38f480f39b8..878cb08c950 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -1674,7 +1674,6 @@ int do_guide(ParticleKey *state, int pa_num, float time, ListBase *lb) /* TODO */ //else{ ///* curve size*/ - // calc_curve_subdiv_radius(cu,cu->nurb.first,((Nurb*)cu->nurb.first)-> //} par.co[0]=par.co[1]=par.co[2]=0.0f; VECCOPY(key.co,pa_loc); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index f2478421737..a193e89d26c 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7868,6 +7868,20 @@ static void do_versions(FileData *fd, Library *lib, Main *main) la->skyblendfac= 1.0f; } } + + /* set the curve radius interpolation to 2.47 default - easy */ + if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 6)) { + Curve *cu; + Nurb *nu; + + for(cu= main->curve.first; cu; cu= cu->id.next) { + for(nu= cu->nurb.first; nu; nu= nu->next) { + if (nu) { + nu->radius_interp = 3; + } + } + } + } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ /* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */ diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 3722c365f39..f809cac037d 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -68,7 +68,7 @@ typedef struct BevList { # # typedef struct BevPoint { - float x, y, z, alfa, sina, cosa, mat[3][3]; + float x, y, z, alfa, radius, sina, cosa, mat[3][3]; short f1, f2; } BevPoint; @@ -115,7 +115,7 @@ typedef struct Nurb { BezTriple *bezt; short tilt_interp; /* KEY_LINEAR, KEY_CARDINAL, KEY_BSPLINE */ - short pad; + short radius_interp; int charidx; } Nurb; diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 8d7e2f673b6..cb2feebfe89 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -3361,9 +3361,9 @@ static void editing_panel_curve_tools(Object *ob, Curve *cu) if(ob->type==OB_CURVE) { uiDefBut(block, LABEL, 0, "Convert", 463,173,72, 18, 0, 0, 0, 0, 0, ""); uiBlockBeginAlign(block); - uiDefBut(block, BUT,B_CONVERTPOLY,"Poly", 467,152,72, 18, 0, 0, 0, 0, 0, "Converts selected into regular Polygon vertices"); - uiDefBut(block, BUT,B_CONVERTBEZ,"Bezier", 467,132,72, 18, 0, 0, 0, 0, 0, "Converts selected to Bezier triples"); - uiDefBut(block, BUT,B_CONVERTNURB,"Nurb", 467,112,72, 18, 0, 0, 0, 0, 0, "Converts selected to Nurbs Points"); + uiDefBut(block, BUT,B_CONVERTPOLY,"Poly", 450,152,110, 18, 0, 0, 0, 0, 0, "Converts selected into regular Polygon vertices"); + uiDefBut(block, BUT,B_CONVERTBEZ,"Bezier", 450,132,110, 18, 0, 0, 0, 0, 0, "Converts selected to Bezier triples"); + uiDefBut(block, BUT,B_CONVERTNURB,"Nurb", 450,112,110, 18, 0, 0, 0, 0, 0, "Converts selected to Nurbs Points"); } uiBlockBeginAlign(block); uiDefBut(block, BUT,B_UNIFU,"Uniform U", 565,152,102, 18, 0, 0, 0, 0, 0, "Nurbs only; interpolated result doesn't go to end points in U"); @@ -3374,7 +3374,7 @@ static void editing_panel_curve_tools(Object *ob, Curve *cu) uiDefBut(block, BUT,B_BEZV,"V", 670,112,50, 18, 0, 0, 0, 0, 0, "Nurbs only; make knots array mimic a Bezier in V"); uiBlockEndAlign(block); - uiDefBut(block, BUT,B_SETWEIGHT,"Set Weight", 465,11,95,49, 0, 0, 0, 0, 0, "Nurbs only; set weight for select points"); + uiDefBut(block, BUT,B_SETWEIGHT,"Set Weight", 450,11,110,49, 0, 0, 0, 0, 0, "Nurbs only; set weight for select points"); uiBlockBeginAlign(block); uiDefButF(block, NUM,0,"Weight:", 565,36,102,22, &editbutweight, 0.01, 100.0, 10, 0, "The weight you can assign"); @@ -3393,10 +3393,15 @@ static void editing_panel_curve_tools(Object *ob, Curve *cu) if(nu) { if (ob->type==OB_CURVE) { uiDefBut(block, LABEL, 0, "Tilt", - 467,87,72, 18, 0, 0, 0, 0, 0, ""); + 450,90,72, 18, 0, 0, 0, 0, 0, ""); /* KEY_LINEAR, KEY_CARDINAL, KEY_BSPLINE */ - uiDefButS(block, MENU, B_TILTINTERP, "Tilt Interpolation %t|Linear %x0|Cardinal %x1|BSpline %x2", - 467,67,72, 18, &(nu->tilt_interp), 0, 0, 0, 0, "Tilt interpolation"); + uiDefButS(block, MENU, B_TILTINTERP, "Tilt Interpolation %t|Linear%x0|Cardinal%x1|BSpline %x2|Ease%x3", + 495,90,66, 18, &(nu->tilt_interp), 0, 0, 0, 0, "Tadius interpolation for 3D curves"); + + uiDefBut(block, LABEL, 0, "Radius", + 450,70,72, 18, 0, 0, 0, 0, 0, ""); + uiDefButS(block, MENU, B_TILTINTERP, "Radius Interpolation %t|Linear%x0|Cardinal%x1|BSpline %x2|Ease%x3", + 495,70,66, 18, &(nu->radius_interp), 0, 0, 0, 0, "Radius interpolation"); } uiBlockBeginAlign(block); diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 527b36d0df4..83eeca5689f 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -4004,16 +4004,14 @@ static void drawnurb(Base *base, Nurb *nurb, int dt) while (nr-->0) { /* accounts for empty bevel lists */ float ox,oy,oz; // Offset perpendicular to the curve float dx,dy,dz; // Delta along the curve - - fac = calc_curve_subdiv_radius(cu, nu, (bl->nr - nr)) * G.scene->editbutsize; - ox = fac*bevp->mat[0][0]; - oy = fac*bevp->mat[0][1]; - oz = fac*bevp->mat[0][2]; + ox = bevp->radius*bevp->mat[0][0]; + oy = bevp->radius*bevp->mat[0][1]; + oz = bevp->radius*bevp->mat[0][2]; - dx = fac*bevp->mat[2][0]; - dy = fac*bevp->mat[2][1]; - dz = fac*bevp->mat[2][2]; + dx = bevp->radius*bevp->mat[2][0]; + dy = bevp->radius*bevp->mat[2][1]; + dz = bevp->radius*bevp->mat[2][2]; glBegin(GL_LINE_STRIP); glVertex3f(bevp->x - ox - dx, bevp->y - oy - dy, bevp->z - oz - dz); -- cgit v1.2.3 From bd85367776a9efb6d4bb70b3d336ced7fe727812 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 23 Sep 2008 15:21:14 +0000 Subject: disable magnification filtering when mipmap is off. useful for texture low poly models. --- source/blender/gpu/intern/gpu_draw.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index fe47fa3c60e..700dd6dedb2 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -222,7 +222,10 @@ static int gpu_get_mipmap(void) static GLenum gpu_get_mipmap_filter() { - return GTS.linearmipmap? GL_LINEAR_MIPMAP_LINEAR: GL_LINEAR_MIPMAP_NEAREST; + /* linearmipmap is off by default + * when mipmapping is off, use unfiltered display */ + return GTS.linearmipmap? GL_LINEAR_MIPMAP_LINEAR : + (GTS.domipmap ? GL_LINEAR_MIPMAP_NEAREST : GL_NEAREST); } /* Set OpenGL state for an MTFace */ @@ -474,12 +477,12 @@ int GPU_verify_image(Image *ima, int tftile, int tfmode, int compare) if (!gpu_get_mipmap()) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter()); } else { gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, rectw, recth, GL_RGBA, GL_UNSIGNED_BYTE, rect); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter()); ima->tpageflag |= IMA_MIPMAP_COMPLETE; } @@ -572,7 +575,7 @@ void GPU_paint_set_mipmap(int mipmap) if(ima->tpageflag & IMA_MIPMAP_COMPLETE) { glBindTexture(GL_TEXTURE_2D, ima->bindcode); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter()); } else GPU_free_image(ima); @@ -585,7 +588,7 @@ void GPU_paint_set_mipmap(int mipmap) if(ima->bindcode) { glBindTexture(GL_TEXTURE_2D, ima->bindcode); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter()); } } } -- cgit v1.2.3 From 3cf87f4c20c8766bf5f58c3800a8bbd67091f1a4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 23 Sep 2008 15:57:05 +0000 Subject: calculate curve radius for drawing curve normals --- source/blender/blenkernel/intern/curve.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index c12fe920594..457bfe20915 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1515,7 +1515,7 @@ void makeBevelList(Object *ob) cu= ob->data; /* do we need to calculate the radius for each point? */ - do_radius = (cu->bevobj || cu->taperobj || (cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ? 0 : 1; + /* do_radius = (cu->bevobj || cu->taperobj || (cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ? 0 : 1; */ /* STEP 1: MAKE POLYS */ @@ -1527,6 +1527,7 @@ void makeBevelList(Object *ob) /* check if we will calculate tilt data */ do_tilt = ((nu->type & CU_2D) && (cu->flag & CU_3D)==0) ? 0 : 1; + do_radius = do_tilt; /* normal display uses the radius, better just to calculate them */ /* check we are a single point? also check we are not a surface and that the orderu is sane, * enforced in the UI but can go wrong possibly */ @@ -1674,7 +1675,7 @@ void makeBevelList(Object *ob) else if((nu->type & 7)==CU_NURBS) { if(nu->pntsv==1) { len= (resolu*SEGMENTSU(nu))+1; - bl= MEM_mallocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList3"); + bl= MEM_callocN(sizeof(BevList)+len*sizeof(BevPoint), "makeBevelList3"); BLI_addtail(&(cu->bev), bl); bl->nr= len; bl->flag= 0; -- cgit v1.2.3 From 005c5e63711e92677547ec2477238fd1f016fb30 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Tue, 23 Sep 2008 20:07:15 +0000 Subject: BGE bug #17657 fixed: dRotY doesn't work properly after 90 degrees rotation. This problem is caused by discontinuities in the conversion orientation matrix -> euler angles: the angle sign can switch and thus the direction of the rotation produced by the dRot Ipo. To avoid this bug, the matrix->euler conversion must be avoided during the game. I took the following approach that is compatible with Blender (identical effect in the game and in the 3D view): - no change in Add mode: Rot and dRot are treated as additional rotation to the orientation at the start of the Ipo. There is no matrix->euler conversion and thus no discontinuities. - Rot Ipo are treated as absolute rotation. All 3 axis should be specified but if they are not, the startup object orientation will be used to set the unspecified axis. By doing a matrix-> euler conversion once at the start, the discontinuities are avoided. If there are also dRot curves, they are treated as delta of the corresponding Rot curve or startup angle. - dRot Ipo are treated as Add mode in Local axis. Note about Add mode: Rot and dRot curves are treated identically during the game. However, only dRot curves make sense because they don't interfere with the object orientation in the 3D view. --- source/gameengine/Ketsji/KX_IPO_SGController.cpp | 115 ++++++++++++++++------- source/gameengine/Ketsji/KX_IPO_SGController.h | 6 ++ 2 files changed, 85 insertions(+), 36 deletions(-) diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.cpp b/source/gameengine/Ketsji/KX_IPO_SGController.cpp index 6223643f75a..67d54cf0b0b 100644 --- a/source/gameengine/Ketsji/KX_IPO_SGController.cpp +++ b/source/gameengine/Ketsji/KX_IPO_SGController.cpp @@ -59,7 +59,9 @@ KX_IpoSGController::KX_IpoSGController() m_ipo_local(false), m_modified(true), m_ipo_start_initialized(false), - m_ipotime(1.0) + m_ipotime(1.0), + m_ipo_start_euler(0.0,0.0,0.0), + m_ipo_euler_initialized(false) { m_game_object = NULL; for (int i=0; i < KX_MAX_IPO_CHANNELS; i++) @@ -136,6 +138,11 @@ bool KX_IpoSGController::Update(double currentTime) m_ipo_start_orient = ob->GetLocalOrientation(); m_ipo_start_scale = ob->GetLocalScale(); m_ipo_start_initialized = true; + if (!m_ipo_euler_initialized) { + // do it only once to avoid angle discontinuities + m_ipo_start_orient.getEuler(m_ipo_start_euler[0], m_ipo_start_euler[1], m_ipo_start_euler[2]); + m_ipo_euler_initialized = true; + } } //modifies position? @@ -199,51 +206,87 @@ bool KX_IpoSGController::Update(double currentTime) ob->GetWorldOrientation() * m_ipo_xform.GetEulerAngles() : m_ipo_xform.GetEulerAngles(), false); } - } else { - double yaw=0, pitch=0, roll=0; //final Euler angles - double tempYaw=0, tempPitch=0, tempRoll=0; //temp holders - if (!m_ipo_add) - ob->GetLocalOrientation().getEuler(yaw, pitch, roll); + } else if (m_ipo_add) { + if (m_ipo_start_initialized) { + double yaw=0, pitch=0, roll=0; //delta Euler angles - //RotX and dRotX - if (m_ipo_channels_active[OB_ROT_X]) { - yaw = (m_ipo_channels_active[OB_DROT_X] ? (m_ipo_xform.GetEulerAngles()[0] + m_ipo_xform.GetDeltaEulerAngles()[0]) : m_ipo_xform.GetEulerAngles()[0] ); - } - else if (m_ipo_channels_active[OB_DROT_X] && m_ipo_start_initialized) { - if (!m_ipo_add) - m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll); - yaw = tempYaw + m_ipo_xform.GetDeltaEulerAngles()[0]; - } + //RotX and dRotX + if (m_ipo_channels_active[OB_ROT_X]) + yaw += m_ipo_xform.GetEulerAngles()[0]; + if (m_ipo_channels_active[OB_DROT_X]) + yaw += m_ipo_xform.GetDeltaEulerAngles()[0]; + + //RotY dRotY + if (m_ipo_channels_active[OB_ROT_Y]) + pitch += m_ipo_xform.GetEulerAngles()[1]; + if (m_ipo_channels_active[OB_DROT_Y]) + pitch += m_ipo_xform.GetDeltaEulerAngles()[1]; + + //RotZ and dRotZ + if (m_ipo_channels_active[OB_ROT_Z]) + roll += m_ipo_xform.GetEulerAngles()[2]; + if (m_ipo_channels_active[OB_DROT_Z]) + roll += m_ipo_xform.GetDeltaEulerAngles()[2]; - //RotY dRotY - if (m_ipo_channels_active[OB_ROT_Y]) { - pitch = (m_ipo_channels_active[OB_DROT_Y] ? (m_ipo_xform.GetEulerAngles()[1] + m_ipo_xform.GetDeltaEulerAngles()[1]) : m_ipo_xform.GetEulerAngles()[1] ); - } - else if (m_ipo_channels_active[OB_DROT_Y] && m_ipo_start_initialized) { - if (!m_ipo_add) - m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll); - pitch = tempPitch + m_ipo_xform.GetDeltaEulerAngles()[1]; - } - - //RotZ and dRotZ - if (m_ipo_channels_active[OB_ROT_Z]) { - roll = (m_ipo_channels_active[OB_DROT_Z] ? (m_ipo_xform.GetEulerAngles()[2] + m_ipo_xform.GetDeltaEulerAngles()[2]) : m_ipo_xform.GetEulerAngles()[2] ); - } - else if (m_ipo_channels_active[OB_DROT_Z] && m_ipo_start_initialized) { - if (!m_ipo_add) - m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll); - roll = tempRoll + m_ipo_xform.GetDeltaEulerAngles()[2]; - } - if (m_ipo_add) { MT_Matrix3x3 rotation(MT_Vector3(yaw, pitch, roll)); if (m_ipo_local) rotation = m_ipo_start_orient * rotation; else rotation = rotation * m_ipo_start_orient; ob->SetLocalOrientation(rotation); - } else { + } + } else if (m_ipo_channels_active[OB_ROT_X] || m_ipo_channels_active[OB_ROT_Y] || m_ipo_channels_active[OB_ROT_Z]) { + if (m_ipo_euler_initialized) { + // assume all channel absolute + // All 3 channels should be specified but if they are not, we will take + // the value at the start of the game to avoid angle sign reversal + double yaw=m_ipo_start_euler[0], pitch=m_ipo_start_euler[1], roll=m_ipo_start_euler[2]; + + //RotX and dRotX + if (m_ipo_channels_active[OB_ROT_X]) { + yaw = (m_ipo_channels_active[OB_DROT_X] ? (m_ipo_xform.GetEulerAngles()[0] + m_ipo_xform.GetDeltaEulerAngles()[0]) : m_ipo_xform.GetEulerAngles()[0] ); + } + else if (m_ipo_channels_active[OB_DROT_X]) { + yaw += m_ipo_xform.GetDeltaEulerAngles()[0]; + } + + //RotY dRotY + if (m_ipo_channels_active[OB_ROT_Y]) { + pitch = (m_ipo_channels_active[OB_DROT_Y] ? (m_ipo_xform.GetEulerAngles()[1] + m_ipo_xform.GetDeltaEulerAngles()[1]) : m_ipo_xform.GetEulerAngles()[1] ); + } + else if (m_ipo_channels_active[OB_DROT_Y]) { + pitch += m_ipo_xform.GetDeltaEulerAngles()[1]; + } + + //RotZ and dRotZ + if (m_ipo_channels_active[OB_ROT_Z]) { + roll = (m_ipo_channels_active[OB_DROT_Z] ? (m_ipo_xform.GetEulerAngles()[2] + m_ipo_xform.GetDeltaEulerAngles()[2]) : m_ipo_xform.GetEulerAngles()[2] ); + } + else if (m_ipo_channels_active[OB_DROT_Z]) { + roll += m_ipo_xform.GetDeltaEulerAngles()[2]; + } ob->SetLocalOrientation(MT_Vector3(yaw, pitch, roll)); } + } else if (m_ipo_start_initialized) { + // only DROT, treat as Add + double yaw=0, pitch=0, roll=0; //delta Euler angles + + //dRotX + if (m_ipo_channels_active[OB_DROT_X]) + yaw = m_ipo_xform.GetDeltaEulerAngles()[0]; + + //dRotY + if (m_ipo_channels_active[OB_DROT_Y]) + pitch = m_ipo_xform.GetDeltaEulerAngles()[1]; + + //dRotZ + if (m_ipo_channels_active[OB_DROT_Z]) + roll = m_ipo_xform.GetDeltaEulerAngles()[2]; + + // dRot are always local + MT_Matrix3x3 rotation(MT_Vector3(yaw, pitch, roll)); + rotation = m_ipo_start_orient * rotation; + ob->SetLocalOrientation(rotation); } } //modifies scale? diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.h b/source/gameengine/Ketsji/KX_IPO_SGController.h index 0bd8980f11c..031b74294ce 100644 --- a/source/gameengine/Ketsji/KX_IPO_SGController.h +++ b/source/gameengine/Ketsji/KX_IPO_SGController.h @@ -72,6 +72,12 @@ class KX_IpoSGController : public SG_Controller /** if IPO initial position has been set for local normal IPO */ bool m_ipo_start_initialized; + /** Euler angles at the start of the game, needed for incomplete ROT Ipo curves */ + class MT_Vector3 m_ipo_start_euler; + + /** true is m_ipo_start_euler has been initialized */ + bool m_ipo_euler_initialized; + /** A reference to the original game object. */ class KX_GameObject* m_game_object; -- cgit v1.2.3 From 7c94eed4cbec462fbe9be59453bebaef224ae478 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 24 Sep 2008 00:23:01 +0000 Subject: Fixing compile warnings --- intern/elbeem/intern/controlparticles.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/intern/elbeem/intern/controlparticles.cpp b/intern/elbeem/intern/controlparticles.cpp index 41e761c0f70..4b496e4a3a2 100644 --- a/intern/elbeem/intern/controlparticles.cpp +++ b/intern/elbeem/intern/controlparticles.cpp @@ -109,8 +109,7 @@ int ControlParticles::initFromObject(ntlGeometryObjModel *model) { ntlVec3Gfx org = start+ntlVec3Gfx(width*0.5); gfxReal distance = -1.; vector inspos; - int approxmax = (int)( ((end[0]-start[0])/width)*((end[1]-start[1])/width)*((end[2]-start[2])/width) ); - + // printf("distance: %f, width: %f\n", distance, width); while(org[2]0.)); t+=tsampling) { ControlParticleSet nextcps; //T mPartSets.push_back(nextcps); @@ -299,6 +297,7 @@ int ControlParticles::getTotalSize() #define LINE_LEN 100 int ControlParticles::initFromTextFile(string filename) { + /* const bool debugRead = false; char line[LINE_LEN]; line[LINE_LEN-1] = '\0'; @@ -341,7 +340,7 @@ int ControlParticles::initFromTextFile(string filename) //if(debugRead) printf("\nDEBUG%d r '%s'\n",lineCnt, line); if(!line) continue; - int len = (int)strlen(line); + size_t len = strlen(line); // skip empty lines and comments (#,//) if(len<1) continue; @@ -503,12 +502,14 @@ int ControlParticles::initFromTextFile(string filename) // done... fclose(infile); applyTrafos(); + */ return 1; } int ControlParticles::initFromTextFileOld(string filename) { + /* const bool debugRead = false; char line[LINE_LEN]; line[LINE_LEN-1] = '\0'; @@ -540,7 +541,7 @@ int ControlParticles::initFromTextFileOld(string filename) if(debugRead) printf("\nDEBUG%d r '%s'\n",lineCnt, line); if(!line) continue; - int len = (int)strlen(line); + size_t len = strlen(line); // skip empty lines and comments (#,//) if(len<1) continue; @@ -622,6 +623,7 @@ int ControlParticles::initFromTextFileOld(string filename) // done... fclose(infile); applyTrafos(); + */ return 1; } -- cgit v1.2.3 From 7eae8d0c7ba8d352faca05e6de4886f3ebd3f169 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 24 Sep 2008 01:39:55 +0000 Subject: Patch #17675: Tooltips for fluid control panel - provided by Kai Kostack --- source/blender/src/buttons_object.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 2cd1bc80223..0b8102cc468 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -5417,16 +5417,16 @@ static void object_panel_fluidsim(Object *ob) uiDefBut ( block, LABEL, 0, "Attraction force:", 0,yline,100,objHeight, NULL, 0.0, 0, 0, 0, "" ); uiBlockBeginAlign ( block ); - uiDefButF ( block, NUM, B_DIFF, "Strength:", 120, yline,90,objHeight, &fss->attractforceStrength, -10.0, 10.0, 10, 0, "Specifies time when the control particles are activated." ); - uiDefButF ( block, NUM, B_DIFF, "Radius:", 210, yline,90,objHeight, &fss->attractforceRadius, 0.0, 10.0, 10, 0, "Specifies time when the control particles are deactivated." ); + uiDefButF ( block, NUM, B_DIFF, "Strength:", 120, yline,90,objHeight, &fss->attractforceStrength, -10.0, 10.0, 10, 0, "Force strength for directional attraction towards the control object." ); + uiDefButF ( block, NUM, B_DIFF, "Radius:", 210, yline,90,objHeight, &fss->attractforceRadius, 0.0, 10.0, 10, 0, "Specifies the force field radius around the control object." ); uiBlockEndAlign ( block ); yline -= lineHeight; yline -= separateHeight; uiDefBut ( block, LABEL, 0, "Velocity force:", 0,yline,100,objHeight, NULL, 0.0, 0, 0, 0, "" ); uiBlockBeginAlign ( block ); - uiDefButF ( block, NUM, B_DIFF, "Strength:", 120, yline,90,objHeight, &fss->velocityforceStrength, 0.0, 10.0, 10, 0, "Specifies time when the control particles are activated." ); - uiDefButF ( block, NUM, B_DIFF, "Radius:", 210, yline,90,objHeight, &fss->velocityforceRadius, 0.0, 10.0, 10, 0, "Specifies time when the control particles are deactivated." ); + uiDefButF ( block, NUM, B_DIFF, "Strength:", 120, yline,90,objHeight, &fss->velocityforceStrength, 0.0, 10.0, 10, 0, "Force strength of how much of the control object's velocity is influencing the fluid velocity." ); + uiDefButF ( block, NUM, B_DIFF, "Radius:", 210, yline,90,objHeight, &fss->velocityforceRadius, 0.0, 10.0, 10, 0, "Specifies the force field radius around the control object." ); uiBlockEndAlign ( block ); yline -= lineHeight; yline -= separateHeight; -- cgit v1.2.3 From 3b09c0b0d5a5bea78f0832532f8c206280ae6456 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Wed, 24 Sep 2008 03:12:10 +0000 Subject: Created a KX_SoftBodyDeformer for real-time soft bodies. Added SetDeformer/GetDeformer() to KX_GameObject. Store mapping between graphics/soft body vertices (work-in-progress) Real-time soft body integration is still very premature, but for a quick preview, see this testfile: http://bulletphysics.com/ftp/pub/test/index.php?dir=blender/&file=soft_test.blend --- .../BroadphaseCollision/btBroadphaseProxy.h | 1 + .../btScaledBvhTriangleMeshShape.cpp | 2 +- .../CollisionShapes/btScaledBvhTriangleMeshShape.h | 12 +- extern/bullet2/src/BulletSoftBody/btSoftBody.h | 5 +- .../BulletSoftBody/btSoftRigidDynamicsWorld.cpp | 9 + .../src/BulletSoftBody/btSoftRigidDynamicsWorld.h | 19 +- extern/bullet2/src/LinearMath/btConvexHull.cpp | 23 ++- extern/bullet2/src/LinearMath/btConvexHull.h | 3 + .../Converter/BL_BlenderDataConversion.cpp | 13 +- .../gameengine/Converter/BL_DeformableGameObject.h | 14 +- source/gameengine/Converter/BL_SkinMeshObject.cpp | 2 +- .../gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp | 110 +++++++++++- source/gameengine/Ketsji/KX_GameObject.h | 8 + source/gameengine/Ketsji/KX_Scene.cpp | 12 +- .../Physics/Bullet/CcdPhysicsController.cpp | 195 ++++++++++++++++----- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 2 + .../Physics/Bullet/CcdPhysicsEnvironment.h | 5 +- 17 files changed, 370 insertions(+), 65 deletions(-) diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h index e0bb67f8521..a074a0b150b 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btBroadphaseProxy.h @@ -46,6 +46,7 @@ IMPLICIT_CONVEX_SHAPES_START_HERE, CONCAVE_SHAPES_START_HERE, //keep all the convex shapetype below here, for the check IsConvexShape in broadphase proxy! TRIANGLE_MESH_SHAPE_PROXYTYPE, + SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE, ///used for demo integration FAST/Swift collision library and Bullet FAST_CONCAVE_MESH_PROXYTYPE, //terrain diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp index 845a5e3005d..2b81a02b557 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp @@ -117,5 +117,5 @@ const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const void btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const { ///don't make this a movable object! - btAssert(0); +// btAssert(0); } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h index 8e1d29fc005..0a1ef8ce5cb 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h @@ -39,7 +39,7 @@ public: virtual int getShapeType() const { //use un-used 'FAST_CONCAVE_MESH_PROXYTYPE' for now, later add SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE to btBroadphaseProxy.h - return FAST_CONCAVE_MESH_PROXYTYPE; + return SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE; } virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; @@ -49,6 +49,16 @@ public: virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + btBvhTriangleMeshShape* getChildShape() + { + return m_bvhTriMeshShape; + } + + const btBvhTriangleMeshShape* getChildShape() const + { + return m_bvhTriMeshShape; + } + //debugging virtual const char* getName()const {return "SCALEDBVHTRIANGLEMESH";} diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.h b/extern/bullet2/src/BulletSoftBody/btSoftBody.h index 4306ed9c471..e89bbcc4fa8 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBody.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.h @@ -29,7 +29,7 @@ subject to the following restrictions: #include "BulletCollision/BroadphaseCollision/btDbvt.h" class btBroadphaseInterface; -class btCollisionDispatcher; +class btDispatcher; /* btSoftBodyWorldInfo */ struct btSoftBodyWorldInfo @@ -39,7 +39,7 @@ struct btSoftBodyWorldInfo btScalar water_offset; btVector3 water_normal; btBroadphaseInterface* m_broadphase; - btCollisionDispatcher* m_dispatcher; + btDispatcher* m_dispatcher; btVector3 m_gravity; btSparseSdf<3> m_sparsesdf; }; @@ -607,6 +607,7 @@ public: virtual ~btSoftBody(); /* Check for existing link */ + btAlignedObjectArray m_userIndexMapping; virtual void setCollisionShape(btCollisionShape* collisionShape) { diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp index 01b9fc0fd35..b363a2efbc1 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.cpp @@ -21,6 +21,10 @@ subject to the following restrictions: #include "btSoftBody.h" #include "btSoftBodyHelpers.h" + + + + btSoftRigidDynamicsWorld::btSoftRigidDynamicsWorld(btDispatcher* dispatcher,btBroadphaseInterface* pairCache,btConstraintSolver* constraintSolver,btCollisionConfiguration* collisionConfiguration) :btDiscreteDynamicsWorld(dispatcher,pairCache,constraintSolver,collisionConfiguration) { @@ -28,6 +32,11 @@ m_drawFlags = fDrawFlags::Std; m_drawNodeTree = true; m_drawFaceTree = false; m_drawClusterTree = false; +m_sbi.m_broadphase = pairCache; +m_sbi.m_dispatcher = dispatcher; +m_sbi.m_sparsesdf.Initialize(); +m_sbi.m_sparsesdf.Reset(); + } btSoftRigidDynamicsWorld::~btSoftRigidDynamicsWorld() diff --git a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h index d0010b65aad..aa8795d897b 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftRigidDynamicsWorld.h @@ -13,12 +13,12 @@ subject to the following restrictions: 3. This notice may not be removed or altered from any source distribution. */ -#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" - #ifndef BT_SOFT_RIGID_DYNAMICS_WORLD_H #define BT_SOFT_RIGID_DYNAMICS_WORLD_H -class btSoftBody; +#include "BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h" +#include "btSoftBody.h" + typedef btAlignedObjectArray btSoftBodyArray; class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld @@ -29,7 +29,8 @@ class btSoftRigidDynamicsWorld : public btDiscreteDynamicsWorld bool m_drawNodeTree; bool m_drawFaceTree; bool m_drawClusterTree; - + btSoftBodyWorldInfo m_sbi; + protected: virtual void predictUnconstraintMotion(btScalar timeStep); @@ -40,7 +41,6 @@ protected: void solveSoftBodiesConstraints(); - public: @@ -57,6 +57,15 @@ public: int getDrawFlags() const { return(m_drawFlags); } void setDrawFlags(int f) { m_drawFlags=f; } + btSoftBodyWorldInfo& getWorldInfo() + { + return m_sbi; + } + const btSoftBodyWorldInfo& getWorldInfo() const + { + return m_sbi; + } + btSoftBodyArray& getSoftBodyArray() { diff --git a/extern/bullet2/src/LinearMath/btConvexHull.cpp b/extern/bullet2/src/LinearMath/btConvexHull.cpp index a20b2059ae9..b8929a86808 100644 --- a/extern/bullet2/src/LinearMath/btConvexHull.cpp +++ b/extern/bullet2/src/LinearMath/btConvexHull.cpp @@ -869,6 +869,8 @@ bool HullLibrary::CleanupVertices(unsigned int svcount, { if ( svcount == 0 ) return false; + m_vertexIndexMapping.resize(0); + #define EPSILON btScalar(0.000001) /* close enough to consider two btScalaring point numbers to be 'the same'. */ @@ -1027,6 +1029,7 @@ bool HullLibrary::CleanupVertices(unsigned int svcount, v[0] = px; v[1] = py; v[2] = pz; + } break; @@ -1041,6 +1044,7 @@ bool HullLibrary::CleanupVertices(unsigned int svcount, dest[2] = pz; vcount++; } + m_vertexIndexMapping.push_back(j); } } @@ -1116,13 +1120,22 @@ bool HullLibrary::CleanupVertices(unsigned int svcount, void HullLibrary::BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount) { + btAlignedObjectArraytmpIndices; + tmpIndices.resize(m_vertexIndexMapping.size()); + int i; + + for (i=0;i(vcount)); memset(&usedIndices[0],0,sizeof(unsigned int)*vcount); ocount = 0; - for (unsigned int i=0; i=0 && ocount <= vcount ); usedIndices[static_cast(v)] = ocount; // assign new index remapping + + } } diff --git a/extern/bullet2/src/LinearMath/btConvexHull.h b/extern/bullet2/src/LinearMath/btConvexHull.h index 8bb80de0225..8c36307dfd6 100644 --- a/extern/bullet2/src/LinearMath/btConvexHull.h +++ b/extern/bullet2/src/LinearMath/btConvexHull.h @@ -192,6 +192,9 @@ class HullLibrary public: + btAlignedObjectArray m_vertexIndexMapping; + + HullError CreateConvexHull(const HullDesc& desc, // describes the input request HullResult& result); // contains the resulst HullError ReleaseResult(HullResult &result); // release memory allocated for this result, we are done with it. diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 9b9d5c95de9..6a5048a9f15 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -743,7 +743,8 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* } // Determine if we need to make a skinned mesh - if (mesh->dvert || mesh->key) { + if (mesh->dvert || mesh->key || ((blenderobj->gameflag & OB_SOFT_BODY) != 0)) + { meshobj = new BL_SkinMeshObject(mesh, lightlayer); skinMesh = true; } @@ -1554,20 +1555,20 @@ static KX_GameObject *gameobject_from_blenderobject( // not that we can have shape keys without dvert! BL_ShapeDeformer *dcont = new BL_ShapeDeformer((BL_DeformableGameObject*)gameobj, ob, (BL_SkinMeshObject*)meshobj); - ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont; + ((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont); if (bHasArmature) dcont->LoadShapeDrivers(ob->parent); } else if (bHasArmature) { BL_SkinDeformer *dcont = new BL_SkinDeformer((BL_DeformableGameObject*)gameobj, ob, (BL_SkinMeshObject*)meshobj); - ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont; + ((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont); } else if (bHasDvert) { // this case correspond to a mesh that can potentially deform but not with the // object to which it is attached for the moment. A skin mesh was created in // BL_ConvertMesh() so must create a deformer too! BL_MeshDeformer *dcont = new BL_MeshDeformer((BL_DeformableGameObject*)gameobj, ob, (BL_SkinMeshObject*)meshobj); - ((BL_DeformableGameObject*)gameobj)->m_pDeformer = dcont; + ((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont); } MT_Point3 min = MT_Point3(center) - MT_Vector3(extents); @@ -2193,8 +2194,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, if (obj && blenderobj->parent && blenderobj->parent->type==OB_ARMATURE && blenderobj->partype==PARSKEL){ KX_GameObject *par = converter->FindGameObject(blenderobj->parent); - if (par && obj->m_pDeformer) - ((BL_SkinDeformer*)obj->m_pDeformer)->SetArmature((BL_ArmatureObject*) par); + if (par && obj->GetDeformer()) + ((BL_SkinDeformer*)obj->GetDeformer())->SetArmature((BL_ArmatureObject*) par); } } } diff --git a/source/gameengine/Converter/BL_DeformableGameObject.h b/source/gameengine/Converter/BL_DeformableGameObject.h index 315ad18c42c..126a1fcb1e7 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.h +++ b/source/gameengine/Converter/BL_DeformableGameObject.h @@ -83,9 +83,21 @@ public: return (m_pDeformer) ? ((BL_MeshDeformer*)m_pDeformer)->GetMesh()->key : NULL; } + virtual void SetDeformer(class RAS_Deformer* deformer) + { + m_pDeformer = deformer; + } + virtual class RAS_Deformer* GetDeformer() + { + return m_pDeformer; + } + public: - RAS_Deformer *m_pDeformer; + protected: + + RAS_Deformer *m_pDeformer; + class BL_ShapeActionActuator *m_activeAct; double m_lastframe; Object* m_blendobj; diff --git a/source/gameengine/Converter/BL_SkinMeshObject.cpp b/source/gameengine/Converter/BL_SkinMeshObject.cpp index 4f9f1a434b5..eb3f9d0588d 100644 --- a/source/gameengine/Converter/BL_SkinMeshObject.cpp +++ b/source/gameengine/Converter/BL_SkinMeshObject.cpp @@ -87,7 +87,7 @@ void BL_SkinMeshObject::UpdateBuckets(void* clientobj,double* oglmatrix,bool use continue; RAS_MeshSlot *slot = *it->m_slots[clientobj]; - slot->m_pDeformer = ((BL_DeformableGameObject*)clientobj)->m_pDeformer; + slot->m_pDeformer = ((BL_DeformableGameObject*)clientobj)->GetDeformer(); } RAS_MeshObject::UpdateBuckets(clientobj, oglmatrix, useObjectColor, rgbavec, visible, culled); diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 46b53d07efc..c4411a58856 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -38,6 +38,8 @@ #include "RAS_MeshObject.h" #include "KX_Scene.h" #include "SYS_System.h" +#include "BL_SkinMeshObject.h" +#include "BulletSoftBody/btSoftBody.h" #include "PHY_Pro.h" //todo cleanup #include "KX_ClientObjectInfo.h" @@ -765,7 +767,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, } case KX_BOUNDMESH: { - if (!ci.m_mass) + if (!ci.m_mass ||objprop->m_softbody) { // mesh shapes can be shared, check first if we already have a shape on that mesh class CcdShapeConstructionInfo *sharedShapeInfo = CcdShapeConstructionInfo::FindMesh(meshobj, false); @@ -988,6 +990,112 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, physicscontroller->SetObject(gameobj->GetSGNode()); + class KX_SoftBodyDeformer : public RAS_Deformer + { + btSoftBody* m_softBody; + class BL_SkinMeshObject* m_pMeshObject; + class BL_DeformableGameObject* m_gameobj; + + + public: + KX_SoftBodyDeformer(btSoftBody* softBody,BL_SkinMeshObject* pMeshObject,BL_DeformableGameObject* gameobj) + : m_softBody(softBody), + m_pMeshObject(pMeshObject), + m_gameobj(gameobj) + { + //printf("KX_SoftBodyDeformer\n"); + }; + + virtual ~KX_SoftBodyDeformer() + { + //printf("~KX_SoftBodyDeformer\n"); + }; + virtual void Relink(GEN_Map*map) + { + //printf("relink\n"); + } + virtual bool Apply(class RAS_IPolyMaterial *polymat) + { + //printf("apply\n"); + RAS_MeshSlot::iterator it; + RAS_MeshMaterial *mmat; + RAS_MeshSlot *slot; + size_t i; + + // update the vertex in m_transverts + Update(); + + // The vertex cache can only be updated for this deformer: + // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object) + // share the same mesh (=the same cache). As the rendering is done per polymaterial + // cycling through the objects, the entire mesh cache cannot be updated in one shot. + mmat = m_pMeshObject->GetMeshMaterial(polymat); + if(!mmat->m_slots[(void*)m_gameobj]) + return true; + + slot = *mmat->m_slots[(void*)m_gameobj]; + + // for each array + for(slot->begin(it); !slot->end(it); slot->next(it)) + { + // for each vertex + // copy the untransformed data from the original mvert + int count = 0; + { + + for(i=it.startvertex; im_nodes); + + if (count == m_softBody->m_userIndexMapping.size()) + { + int index = 0; + for(i=it.startvertex; im_userIndexMapping[index]].m_x.getX(), + nodes[m_softBody->m_userIndexMapping[index]].m_x.getY(), + nodes[m_softBody->m_userIndexMapping[index]].m_x.getZ()); + v.SetXYZ(pt); + + //(m_transverts[v.getOrigIndex()]); + } + } + + } + + return true; + } + virtual bool Update(void) + { + //printf("update\n"); + return true;//?? + } + virtual RAS_Deformer *GetReplica() + { + //printf("getReplica\n"); + return 0; + } + protected: + //class RAS_MeshObject *m_pMesh; + }; + + ///test for soft bodies + if (objprop->m_softbody && physicscontroller) + { + btSoftBody* softBody = physicscontroller->GetSoftBody(); + if (softBody && gameobj->GetMesh(0)) + { + //should be a mesh then, so add a soft body deformer + KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer(softBody, (BL_SkinMeshObject*)gameobj->GetMesh(0),(BL_DeformableGameObject*)gameobj); + gameobj->SetDeformer(softbodyDeformer); + + } + } + } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 2da0be4df25..12e29cf3294 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -332,6 +332,14 @@ public: m_pPhysicsController1 = physicscontroller; } + virtual class RAS_Deformer* GetDeformer() + { + return 0; + } + virtual void SetDeformer(class RAS_Deformer* deformer) + { + + } /** * @section Coordinate system manipulation functions diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 04db96c298c..6eeb732c1e3 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -977,10 +977,10 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) { BL_DeformableGameObject* newobj = static_cast( gameobj ); - if (newobj->m_pDeformer) + if (newobj->GetDeformer()) { - delete newobj->m_pDeformer; - newobj->m_pDeformer = NULL; + delete newobj->GetDeformer(); + newobj->SetDeformer(NULL); } if (mesh->IsDeformed()) @@ -1030,7 +1030,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) NULL ); } - newobj->m_pDeformer = shapeDeformer; + newobj->SetDeformer( shapeDeformer); } else if (bHasArmature) { @@ -1042,14 +1042,14 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) static_cast( parentobj ) ); releaseParent= false; - newobj->m_pDeformer = skinDeformer; + newobj->SetDeformer(skinDeformer); } else if (bHasDvert) { BL_MeshDeformer* meshdeformer = new BL_MeshDeformer( newobj, oldblendobj, static_cast(mesh) ); - newobj->m_pDeformer = meshdeformer; + newobj->SetDeformer(meshdeformer); } // release parent reference if its not being used diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 41ae5e38309..ad79db16dc4 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -20,7 +20,11 @@ subject to the following restrictions: #include "CcdPhysicsEnvironment.h" #include "RAS_MeshObject.h" #include "BulletSoftBody/btSoftBody.h" +#include "BulletSoftBody//btSoftBodyInternals.h" +#include "BulletSoftBody/btSoftBodyHelpers.h" +#include "LinearMath/btConvexHull.h" +#include "BulletSoftBody/btSoftRigidDynamicsWorld.h" class BP_Proxy; @@ -135,11 +139,7 @@ btSoftBody* CcdPhysicsController::GetSoftBody() #include "BulletSoftBody/btSoftBodyHelpers.h" -btVector3 pts[3] = {btVector3(0,0,0), -btVector3(0,1,0), -btVector3(1,1,0)}; -int triangles[3] = {0,1,2}; -btSoftBodyWorldInfo sbi; + void CcdPhysicsController::CreateRigidbody() { @@ -151,8 +151,13 @@ void CcdPhysicsController::CreateRigidbody() //create a collision object + int shapeType = m_cci.m_collisionShape ? m_cci.m_collisionShape->getShapeType() : 0; + //disable soft body until first sneak preview is ready - if (0)//m_cci.m_bSoft) + if (m_cci.m_bSoft && m_cci.m_collisionShape && + (shapeType == CONVEX_HULL_SHAPE_PROXYTYPE)) + //(shapeType == TRIANGLE_MESH_SHAPE_PROXYTYPE) | + //(shapeType == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE))) { btRigidBody::btRigidBodyConstructionInfo rbci(m_cci.m_mass,m_bulletMotionState,m_collisionShape,m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); rbci.m_linearDamping = m_cci.m_linearDamping; @@ -161,54 +166,161 @@ void CcdPhysicsController::CreateRigidbody() rbci.m_restitution = m_cci.m_restitution; - sbi.m_broadphase = this->m_cci.m_physicsEnv->getBroadphase(); - sbi.m_dispatcher = (btCollisionDispatcher*) m_cci.m_physicsEnv->getDispatcher(); - int nodecount = 0; - int numtriangles = 1; - btVector3 p = trans.getOrigin(); + btVector3 p(0,0,0);// = getOrigin(); btScalar h = 1.f; + btSoftRigidDynamicsWorld* softDynaWorld = (btSoftRigidDynamicsWorld*)m_cci.m_physicsEnv->getDynamicsWorld(); + PHY__Vector3 grav; - m_cci.m_physicsEnv->getGravity(grav); - sbi.m_gravity.setValue(grav[0],grav[1],grav[2]); - - const btVector3 c[]={ p+h*btVector3(-1,-1,-1), - p+h*btVector3(+1,-1,-1), - p+h*btVector3(-1,+1,-1), - p+h*btVector3(+1,+1,-1), - p+h*btVector3(-1,-1,+1), - p+h*btVector3(+1,-1,+1), - p+h*btVector3(-1,+1,+1), - p+h*btVector3(+1,+1,+1)}; - - int i=0; - const int n=15; + grav[0] = softDynaWorld->getGravity().getX(); + grav[1] = softDynaWorld->getGravity().getY(); + grav[2] = softDynaWorld->getGravity().getZ(); + softDynaWorld->getWorldInfo().m_gravity.setValue(grav[0],grav[1],grav[2]); //?? + + //btSoftBody* psb=btSoftBodyHelpers::CreateRope(sbi, btVector3(-10,0,i*0.25),btVector3(10,0,i*0.25), 16,1+2); - btSoftBody* psb = btSoftBodyHelpers::CreateFromConvexHull(sbi,c,8); - m_object = psb;//btSoftBodyHelpers::CreateFromTriMesh(sbi,&pts[0].getX(),triangles,numtriangles); + btSoftBody* psb = 0; + + if (m_cci.m_collisionShape->getShapeType() == CONVEX_HULL_SHAPE_PROXYTYPE) + { + btConvexHullShape* convexHull = (btConvexHullShape* )m_cci.m_collisionShape; + btAlignedObjectArray transformedVertices; + transformedVertices.resize(convexHull->getNumPoints()); + for (int i=0;igetNumPoints();i++) + { + transformedVertices[i] = trans(convexHull->getPoints()[i]); + } + + //psb = btSoftBodyHelpers::CreateFromConvexHull(sbi,&transformedVertices[0],convexHull->getNumPoints()); + + { + int nvertices = convexHull->getNumPoints(); + const btVector3* vertices = &transformedVertices[0]; + btSoftBodyWorldInfo& worldInfo = softDynaWorld->getWorldInfo(); + + HullDesc hdsc(QF_TRIANGLES,nvertices,vertices); + HullResult hres; + HullLibrary hlib;/*??*/ + hdsc.mMaxVertices=nvertices; + hlib.CreateConvexHull(hdsc,hres); + + psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices, + &hres.m_OutputVertices[0],0); + for(int i=0;i<(int)hres.mNumFaces;++i) + { + const int idx[]={ hres.m_Indices[i*3+0], + hres.m_Indices[i*3+1], + hres.m_Indices[i*3+2]}; + if(idx[0]appendLink( idx[0],idx[1]); + if(idx[1]appendLink( idx[1],idx[2]); + if(idx[2]appendLink( idx[2],idx[0]); + psb->appendFace(idx[0],idx[1],idx[2]); + } + + { + for (int i=0;im_userIndexMapping.push_back(hlib.m_vertexIndexMapping[i]); + //psb->m_userIndexMapping.push_back(hres.m_Indices[i]); + } + + hlib.ReleaseResult(hres); + psb->randomizeConstraints(); + + } + + - psb->m_cfg.collisions = btSoftBody::fCollision::SDF_RS;//btSoftBody::fCollision::CL_SS+ btSoftBody::fCollision::CL_RS; - sbi.m_sparsesdf.Reset(); - sbi.m_sparsesdf.Initialize(); - psb->generateBendingConstraints(2); - psb->m_cfg.kDF=1; - psb->activate(); - psb->setActivationState(1); - psb->setDeactivationTime(1.f); - psb->m_cfg.piterations = 4; + } else + { + /* + if (m_cci.m_collisionShape->getShapeType() ==SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) + { + btScaledBvhTriangleMeshShape* scaledtrimeshshape = (btScaledBvhTriangleMeshShape*) m_cci.m_collisionShape; + btBvhTriangleMeshShape* trimeshshape = scaledtrimeshshape->getChildShape(); + + ///only deal with meshes that have 1 sub part/component, for now + if (trimeshshape->getMeshInterface()->getNumSubParts()==1) + { + unsigned char* vertexBase; + PHY_ScalarType vertexType; + int numverts; + int vertexstride; + unsigned char* indexbase; + int indexstride; + int numtris; + PHY_ScalarType indexType; + trimeshshape->getMeshInterface()->getLockedVertexIndexBase(&vertexBase,numverts,vertexType,vertexstride,&indexbase,indexstride,numtris,indexType); + + psb = btSoftBodyHelpers::CreateFromTriMesh(sbi,(const btScalar*)vertexBase,(const int*)indexbase,numtris); + } + } else + { + btBvhTriangleMeshShape* trimeshshape = (btBvhTriangleMeshShape*) m_cci.m_collisionShape; + ///only deal with meshes that have 1 sub part/component, for now + if (trimeshshape->getMeshInterface()->getNumSubParts()==1) + { + unsigned char* vertexBase; + PHY_ScalarType vertexType; + int numverts; + int vertexstride; + unsigned char* indexbase; + int indexstride; + int numtris; + PHY_ScalarType indexType; + trimeshshape->getMeshInterface()->getLockedVertexIndexBase(&vertexBase,numverts,vertexType,vertexstride,&indexbase,indexstride,numtris,indexType); + + psb = btSoftBodyHelpers::CreateFromTriMesh(sbi,(const btScalar*)vertexBase,(const int*)indexbase,numtris); + } + + + //psb = btSoftBodyHelpers::CreateFromTriMesh(sbi,&pts[0].getX(),triangles,numtriangles); + } + */ + + } + + + m_object = psb; + + //psb->m_cfg.collisions = btSoftBody::fCollision::SDF_RS;//btSoftBody::fCollision::CL_SS+ btSoftBody::fCollision::CL_RS; + psb->m_cfg.collisions = btSoftBody::fCollision::SDF_RS + btSoftBody::fCollision::CL_SS; + + //btSoftBody::Material* pm=psb->appendMaterial(); + btSoftBody::Material* pm=psb->m_materials[0]; + pm->m_kLST = 0.1f; + //pm->m_kAST = 0.01f; + //pm->m_kVST = 0.001f; + psb->generateBendingConstraints(2,pm); +/* + psb->m_cfg.kDF = 0.1f;//1.f; + psb->m_cfg.kDP = 0.0001; + //psb->m_cfg.kDP = 0.005; + psb->m_cfg.kCHR = 0.1; + //psb->m_cfg.kVCF = 0.1f; + psb->m_cfg.kVCF = 0.0001f; + //psb->m_cfg.kAHR = 0.1f; + psb->m_cfg.kAHR = 0.0001f; + psb->m_cfg.kMT = 0.1f; + //psb->m_cfg.kDF=1; + */ + +// psb->activate(); +// psb->setActivationState(1); +// psb->setDeactivationTime(1.f); + //psb->m_cfg.piterations = 4; //psb->m_materials[0]->m_kLST = 0.1+(i/(btScalar)(n-1))*0.9; - psb->setTotalMass(20); + psb->setTotalMass(m_cci.m_mass); + psb->generateClusters(64); psb->setCollisionFlags(0); - - m_object->setCollisionShape(rbci.m_collisionShape); +// m_object->setCollisionShape(rbci.m_collisionShape); btTransform startTrans; if (rbci.m_motionState) @@ -218,8 +330,13 @@ void CcdPhysicsController::CreateRigidbody() { startTrans = rbci.m_startWorldTransform; } + startTrans.setIdentity(); + m_object->setWorldTransform(startTrans); m_object->setInterpolationWorldTransform(startTrans); + m_MotionState->setWorldPosition(0,0,0); + m_MotionState->setWorldOrientation(0,0,0,1); + } else { diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 96aa9ad164e..8c5aae3f8c9 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -452,6 +452,8 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl) } + + void CcdPhysicsEnvironment::removeCcdPhysicsController(CcdPhysicsController* ctrl) { //also remove constraint diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 9b6a76d49ee..56a639509c5 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -216,7 +216,10 @@ protected: void SyncMotionStates(float timeStep); - + class btSoftRigidDynamicsWorld* getDynamicsWorld() + { + return m_dynamicsWorld; + } class btConstraintSolver* GetConstraintSolver(); -- cgit v1.2.3 From 48bc5b2ac654229832752e7f8593f0dda2ccf80c Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 24 Sep 2008 11:52:31 +0000 Subject: Made Object-level copy constraints work the same as for bones now too --- source/blender/blenkernel/intern/modifier.c | 366 +++++++++++++++++++++++++++ source/blender/makesdna/DNA_modifier_types.h | 19 ++ source/blender/src/buttons_editing.c | 27 ++ source/blender/src/drawaction.c | 4 + source/blender/src/editobject.c | 4 - 5 files changed, 416 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 56b4aa574c7..be18c0a873a 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -54,6 +54,7 @@ #include "MEM_guardedalloc.h" +#include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_camera_types.h" #include "DNA_cloth_types.h" @@ -587,6 +588,361 @@ static DerivedMesh *buildModifier_applyModifier(ModifierData *md, Object *ob, return result; } +/* Mask */ + +static void maskModifier_copyData(ModifierData *md, ModifierData *target) +{ + MaskModifierData *mmd = (MaskModifierData*) md; + MaskModifierData *tmmd = (MaskModifierData*) target; + + strcpy(tmmd->vgroup, mmd->vgroup); +} + +static CustomDataMask maskModifier_requiredDataMask(ModifierData *md) +{ + return (1 << CD_MDEFORMVERT); +} + +static void maskModifier_foreachObjectLink( + ModifierData *md, Object *ob, + void (*walk)(void *userData, Object *ob, Object **obpoin), + void *userData) +{ + MaskModifierData *mmd = (MaskModifierData *)md; + walk(userData, ob, &mmd->ob_arm); +} + +static void maskModifier_updateDepgraph(ModifierData *md, DagForest *forest, + Object *ob, DagNode *obNode) +{ + MaskModifierData *mmd = (MaskModifierData *)md; + + if (mmd->ob_arm) + { + DagNode *armNode = dag_get_node(forest, mmd->ob_arm); + + dag_add_relation(forest, armNode, obNode, + DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Mask Modifier"); + } +} + +static DerivedMesh *maskModifier_applyModifier(ModifierData *md, Object *ob, + DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) +{ + MaskModifierData *mmd= (MaskModifierData *)md; + DerivedMesh *dm= derivedData, *result= NULL; + GHash *vertHash=NULL, *edgeHash, *faceHash; + GHashIterator *hashIter; + MDeformVert *dvert= NULL; + int numFaces=0, numEdges=0, numVerts=0; + int maxVerts, maxEdges, maxFaces; + int i; + + /* Overview of Method: + * 1. Get the vertices that are in the vertexgroup of interest + * 2. Filter out unwanted geometry (i.e. not in vertexgroup), by populating mappings with new vs old indices + * 3. Make a new mesh containing only the mapping data + */ + + /* get original number of verts, edges, and faces */ + maxVerts= dm->getNumVerts(dm); + maxEdges= dm->getNumEdges(dm); + maxFaces= dm->getNumFaces(dm); + + /* check if we can just return the original mesh + * - must have verts and therefore verts assigned to vgroups to do anything useful + */ + if ( !(ELEM(mmd->mode, MOD_MASK_MODE_ARM, MOD_MASK_MODE_VGROUP)) || + (maxVerts == 0) || (ob->defbase.first == NULL) ) + { + return derivedData; + } + + /* if mode is to use selected armature bones, aggregate the bone groups */ + if (mmd->mode == MOD_MASK_MODE_ARM) /* --- using selected bones --- */ + { + GHash *vgroupHash, *boneHash; + Object *oba= mmd->ob_arm; + bPoseChannel *pchan; + bDeformGroup *def; + + /* check that there is armature object with bones to use, otherwise return original mesh */ + if (ELEM(NULL, mmd->ob_arm, mmd->ob_arm->pose)) + return derivedData; + + /* hashes for finding mapping of: + * - vgroups to indicies -> vgroupHash (string, int) + * - bones to vgroup indices -> boneHash (index of vgroup, dummy) + */ + vgroupHash= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp); + boneHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + + /* build mapping of names of vertex groups to indices */ + for (i = 0, def = ob->defbase.first; def; def = def->next, i++) + BLI_ghash_insert(vgroupHash, def->name, SET_INT_IN_POINTER(i)); + + /* get selected-posechannel <-> vertexgroup index mapping */ + for (pchan= oba->pose->chanbase.first; pchan; pchan= pchan->next) + { + /* check if bone is selected */ + // TODO: include checks for visibility too? + // FIXME: the depsgraph needs extensions to make this work in realtime... + if ( (pchan->bone) && (pchan->bone->flag & BONE_SELECTED) ) + { + /* check if hash has group for this bone */ + if (BLI_ghash_haskey(vgroupHash, pchan->name)) + { + int defgrp_index= GET_INT_FROM_POINTER(BLI_ghash_lookup(vgroupHash, pchan->name)); + + /* add index to hash (store under key only) */ + BLI_ghash_insert(boneHash, SET_INT_IN_POINTER(defgrp_index), pchan); + } + } + } + + /* if no bones selected, free hashes and return original mesh */ + if (BLI_ghash_size(boneHash) == 0) + { + BLI_ghash_free(vgroupHash, NULL, NULL); + BLI_ghash_free(boneHash, NULL, NULL); + + return derivedData; + } + + /* repeat the previous check, but for dverts */ + dvert= dm->getVertDataArray(dm, CD_MDEFORMVERT); + if (dvert == NULL) + { + BLI_ghash_free(vgroupHash, NULL, NULL); + BLI_ghash_free(boneHash, NULL, NULL); + + return derivedData; + } + + /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ + vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + + /* add vertices which exist in vertexgroups into vertHash for filtering */ + for (i = 0; i < maxVerts; i++) + { + MDeformWeight *def_weight = NULL; + int j; + + for (j= 0; j < dvert[i].totweight; j++) + { + if (BLI_ghash_haskey(boneHash, SET_INT_IN_POINTER(dvert[i].dw[j].def_nr))) + { + def_weight = &dvert[i].dw[j]; + break; + } + } + + /* check if include vert in vertHash */ + if (mmd->flag & MOD_MASK_INV) { + /* if this vert is in the vgroup, don't include it in vertHash */ + if (def_weight) continue; + } + else { + /* if this vert isn't in the vgroup, don't include it in vertHash */ + if (!def_weight) continue; + } + + /* add to ghash for verts (numVerts acts as counter for mapping) */ + BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts)); + numVerts++; + } + + /* free temp hashes */ + BLI_ghash_free(vgroupHash, NULL, NULL); + BLI_ghash_free(boneHash, NULL, NULL); + } + else /* --- Using Nominated VertexGroup only --- */ + { + int defgrp_index = -1; + + /* get index of vertex group */ + if (mmd->vgroup[0]) + { + bDeformGroup *def; + + /* find index by comparing names - SLOW... */ + for (i = 0, def = ob->defbase.first; def; def = def->next, i++) + { + if (!strcmp(def->name, mmd->vgroup)) + { + defgrp_index = i; + break; + } + } + } + + /* get dverts */ + if (defgrp_index >= 0) + dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); + + /* if no vgroup (i.e. dverts) found, return the initial mesh */ + if ((defgrp_index < 0) || (dvert == NULL)) + return dm; + + /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ + vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + + /* add vertices which exist in vertexgroup into ghash for filtering */ + for (i = 0; i < maxVerts; i++) + { + MDeformWeight *def_weight = NULL; + int j; + + for (j= 0; j < dvert[i].totweight; j++) + { + if (dvert[i].dw[j].def_nr == defgrp_index) + { + def_weight = &dvert[i].dw[j]; + break; + } + } + + /* check if include vert in vertHash */ + if (mmd->flag & MOD_MASK_INV) { + /* if this vert is in the vgroup, don't include it in vertHash */ + if (def_weight) continue; + } + else { + /* if this vert isn't in the vgroup, don't include it in vertHash */ + if (!def_weight) continue; + } + + /* add to ghash for verts (numVerts acts as counter for mapping) */ + BLI_ghash_insert(vertHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numVerts)); + numVerts++; + } + } + + /* hashes for quickly providing a mapping from old to new - use key=oldindex, value=newindex */ + edgeHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + faceHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp); + + /* loop over edges and faces, and do the same thing to + * ensure that they only reference existing verts + */ + for (i = 0; i < maxEdges; i++) + { + MEdge me; + dm->getEdge(dm, i, &me); + + /* only add if both verts will be in new mesh */ + if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v1)) && + BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(me.v2)) ) + { + BLI_ghash_insert(edgeHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numEdges)); + numEdges++; + } + } + for (i = 0; i < maxFaces; i++) + { + MFace mf; + dm->getFace(dm, i, &mf); + + /* all verts must be available */ + if ( BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v1)) && + BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v2)) && + BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v3)) && + (mf.v4==0 || BLI_ghash_haskey(vertHash, SET_INT_IN_POINTER(mf.v4))) ) + { + BLI_ghash_insert(faceHash, SET_INT_IN_POINTER(i), SET_INT_IN_POINTER(numFaces)); + numFaces++; + } + } + + + /* now we know the number of verts, edges and faces, + * we can create the new (reduced) mesh + */ + result = CDDM_from_template(dm, numVerts, numEdges, numFaces); + + + /* using ghash-iterators, map data into new mesh */ + /* vertices */ + for ( hashIter = BLI_ghashIterator_new(vertHash); + !BLI_ghashIterator_isDone(hashIter); + BLI_ghashIterator_step(hashIter) ) + { + MVert source; + MVert *dest; + int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); + int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); + + dm->getVert(dm, oldIndex, &source); + dest = CDDM_get_vert(result, newIndex); + + DM_copy_vert_data(dm, result, oldIndex, newIndex, 1); + *dest = source; + } + BLI_ghashIterator_free(hashIter); + + /* edges */ + for ( hashIter = BLI_ghashIterator_new(edgeHash); + !BLI_ghashIterator_isDone(hashIter); + BLI_ghashIterator_step(hashIter) ) + { + MEdge source; + MEdge *dest; + int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); + int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); + + dm->getEdge(dm, oldIndex, &source); + dest = CDDM_get_edge(result, newIndex); + + source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); + source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); + + DM_copy_edge_data(dm, result, oldIndex, newIndex, 1); + *dest = source; + } + BLI_ghashIterator_free(hashIter); + + /* faces */ + for ( hashIter = BLI_ghashIterator_new(faceHash); + !BLI_ghashIterator_isDone(hashIter); + BLI_ghashIterator_step(hashIter) ) + { + MFace source; + MFace *dest; + int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); + int newIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(hashIter)); + int orig_v4; + + dm->getFace(dm, oldIndex, &source); + dest = CDDM_get_face(result, newIndex); + + orig_v4 = source.v4; + + source.v1 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v1))); + source.v2 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v2))); + source.v3 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v3))); + if (source.v4) + source.v4 = GET_INT_FROM_POINTER(BLI_ghash_lookup(vertHash, SET_INT_IN_POINTER(source.v4))); + + DM_copy_face_data(dm, result, oldIndex, newIndex, 1); + *dest = source; + + test_index_face(dest, &result->faceData, newIndex, (orig_v4 ? 4 : 3)); + } + BLI_ghashIterator_free(hashIter); + + /* recalculate normals */ + CDDM_calc_normals(result); + + /* free hashes */ + BLI_ghash_free(vertHash, NULL, NULL); + BLI_ghash_free(edgeHash, NULL, NULL); + BLI_ghash_free(faceHash, NULL, NULL); + + /* return the new mesh */ + return result; +} + /* Array */ /* Array modifier: duplicates the object multiple times along an axis */ @@ -7519,6 +7875,15 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->copyData = buildModifier_copyData; mti->dependsOnTime = buildModifier_dependsOnTime; mti->applyModifier = buildModifier_applyModifier; + + mti = INIT_TYPE(Mask); + mti->type = eModifierTypeType_Nonconstructive; + mti->flags = eModifierTypeFlag_AcceptsMesh; + mti->copyData = maskModifier_copyData; + mti->requiredDataMask= maskModifier_requiredDataMask; + mti->foreachObjectLink = maskModifier_foreachObjectLink; + mti->updateDepgraph = maskModifier_updateDepgraph; + mti->applyModifier = maskModifier_applyModifier; mti = INIT_TYPE(Array); mti->type = eModifierTypeType_Constructive; @@ -8211,3 +8576,4 @@ void modifier_freeTemporaryData(ModifierData *md) } + diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 114dfe10bae..3e8f8702003 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -37,6 +37,7 @@ typedef enum ModifierType { eModifierType_Bevel, eModifierType_Shrinkwrap, eModifierType_Fluidsim, + eModifierType_Mask, NUM_MODIFIER_TYPES } ModifierType; @@ -105,6 +106,24 @@ typedef struct BuildModifierData { int randomize, seed; } BuildModifierData; +/* Mask Modifier */ +typedef struct MaskModifierData { + ModifierData modifier; + + struct Object *ob_arm; /* armature to use to in place of hardcoded vgroup */ + char vgroup[32]; /* name of vertex group to use to mask */ + + int mode; /* using armature or hardcoded vgroup */ + int flag; /* flags for various things */ +} MaskModifierData; + +/* Mask Modifier -> mode */ +#define MOD_MASK_MODE_VGROUP 0 +#define MOD_MASK_MODE_ARM 1 + +/* Mask Modifier -> flag */ +#define MOD_MASK_INV (1<<0) + typedef struct ArrayModifierData { ModifierData modifier; diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index cb2feebfe89..44e0008576a 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1850,6 +1850,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco } else if (smd->shrinkType == MOD_SHRINKWRAP_NEAREST_SURFACE) height += 19; + } else if (md->type == eModifierType_Mask) { + height = 66; } /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */ uiDefBut(block, ROUNDBOX, 0, "", x-10, y-height-2, width, height-2, NULL, 5.0, 0.0, 12, 40, ""); @@ -2128,6 +2130,30 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiDefButF(block, NUM, B_MODIFIER_RECALC, "Ratio:", lx,(cy-=19),buttonWidth,19, &dmd->percent, 0.0, 1.0, 10, 0, "Defines the percentage of triangles to reduce to"); sprintf(str, "Face Count: %d", dmd->faceCount); uiDefBut(block, LABEL, 1, str, lx, (cy-=19), 160,19, NULL, 0.0, 0.0, 0, 0, "Displays the current number of faces in the decimated mesh"); + } else if (md->type==eModifierType_Mask) { + MaskModifierData *mmd = (MaskModifierData *)md; + + sprintf(str, "Mask Mode%%t|Vertex Group%%x%d|Selected Bones%%x%d|", + MOD_MASK_MODE_VGROUP,MOD_MASK_MODE_ARM); + uiDefButI(block, MENU, B_MODIFIER_RECALC, str, + lx, (cy -= 19), buttonWidth, 19, &mmd->mode, + 0.0, 1.0, 0, 0, "How masking region is defined"); + + if (mmd->mode == MOD_MASK_MODE_ARM) { + uiDefIDPoinBut(block, modifier_testArmatureObj, ID_OB, B_CHANGEDEP, + "Ob: ", lx, (cy -= 19), buttonWidth, 19, &mmd->ob_arm, + "Armature to use as source of bones to mask"); + } + else { + but=uiDefBut(block, TEX, B_MODIFIER_RECALC, "VGroup: ", + lx, (cy-=19), buttonWidth, 19, &mmd->vgroup, + 0.0, 31.0, 0, 0, "Vertex Group name"); + uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ob); + } + + uiDefButBitI(block, TOG, MOD_MASK_INV, B_MODIFIER_RECALC, "Inverse", + lx, (cy-=19), buttonWidth, 19, &mmd->flag, + 0, 0, 0, 0, "Use vertices that are not part of region defined"); } else if (md->type==eModifierType_Smooth) { SmoothModifierData *smd = (SmoothModifierData*) md; @@ -2266,6 +2292,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiDefBut(block, LABEL, 1, "See Soft Body panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, ""); } else if (md->type==eModifierType_Cloth) { uiDefBut(block, LABEL, 1, "See Cloth panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, ""); + } else if (md->type==eModifierType_Collision) { uiDefBut(block, LABEL, 1, "See Collision panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, ""); } else if (md->type==eModifierType_Fluidsim) { diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index dfbe17179a4..64e85bfcd4e 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -1459,6 +1459,10 @@ static void add_bezt_to_keyblockslist(ListBase *blocks, IpoCurve *icu, int index * Note: we can't search from end to try to optimise this as it causes errors there's * an A ___ B |---| B situation */ + // FIXME: here there is a bug where we are trying to get the summary for the following channels + // A|--------------|A ______________ B|--------------|B + // A|------------------------------------------------|A + // A|----|A|---|A|-----------------------------------|A for (ab= blocks->first; ab; ab= ab->next) { /* check if alter existing block or add new block */ if (ab->start == prev->vec[1][0]) { diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index a52882e6003..6c830c7febf 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -3624,10 +3624,6 @@ void copy_attr(short event) } } else if(event==22) { - /* Clear the constraints on the target */ - free_constraints(&base->object->constraints); - free_constraint_channels(&base->object->constraintChannels); - /* Copy the constraint channels over */ copy_constraints(&base->object->constraints, &ob->constraints); if (U.dupflag& USER_DUP_IPO) -- cgit v1.2.3 From 38a80ff9a5c6d7bebef42bc3b8320d781b4e4f1c Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Wed, 24 Sep 2008 22:58:49 +0000 Subject: BGE patch: add advanced parameters for SoftBody. Add Rasterizer.drawLine() Python function. --- source/blender/blenkernel/intern/object.c | 4 ++++ source/blender/blenloader/intern/readfile.c | 4 ++++ source/blender/makesdna/DNA_object_types.h | 12 ++++++++++- source/blender/src/buttons_logic.c | 23 +++++++++++++++++++-- source/blender/src/editobject.c | 4 ++++ source/gameengine/Ketsji/KX_PythonInit.cpp | 32 +++++++++++++++++++++++++++++ source/gameengine/PyDoc/Rasterizer.py | 11 ++++++++++ 7 files changed, 87 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 0da69ef5168..54908230d88 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -964,6 +964,10 @@ Object *add_only_object(int type, char *name) ob->anisotropicFriction[2] = 1.0f; ob->gameflag= OB_PROP|OB_COLLISION; ob->margin = 0.0; + ob->linearStiffness = 1.0f; + ob->angularStiffness = 1.0f; + ob->volumePreservation = 1.0f; + ob->gamesoftFlag = 0; /* NT fluid sim defaults */ ob->fluidsimFlag = 0; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index a193e89d26c..d966d691fdd 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7849,6 +7849,10 @@ static void do_versions(FileData *fd, Library *lib, Main *main) // Before it was conditioning all the other dynamic flags if (!(ob->gameflag & OB_ACTOR)) ob->gameflag &= ~(OB_GHOST|OB_DYNAMIC|OB_RIGID_BODY|OB_SOFT_BODY|OB_COLLISION_RESPONSE); + /* suitable default for older files */ + ob->linearStiffness = 1.0f; + ob->angularStiffness = 1.0f; + ob->volumePreservation = 1.0f; } } diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 66bdaf2c98b..041e0eaebde 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -156,7 +156,14 @@ typedef struct Object { float formfactor; float rdamping, sizefac; - float margin, pad3; + float margin; + /* for game engine soft body */ + float linearStiffness; + float angularStiffness; + float volumePreservation; + int gamesoftFlag; + int pad3; + char dt, dtx; @@ -411,6 +418,9 @@ extern Object workob; #define OB_RECALC_TIME 4 #define OB_RECALC 7 +/* ob->gamesoftFlag */ +#define OB_SOFT_SHAPE_MATCHING 1 + /* ob->gameflag */ #define OB_DYNAMIC 1 #define OB_CHILD 2 diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 96949756083..667f822bed5 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -2979,11 +2979,11 @@ static uiBlock *advanced_bullet_menu(void *arg_ob) { uiBlock *block; Object *ob = arg_ob; - short yco = 65, xco = 0; + short yco = 105, xco = 0; block= uiNewBlock(&curarea->uiblocks, "advanced_bullet_options", UI_EMBOSS, UI_HELV, curarea->win); /* use this for a fake extra empy space around the buttons */ - uiDefBut(block, LABEL, 0, "", -5, -10, 255, 100, NULL, 0, 0, 0, 0, ""); + uiDefBut(block, LABEL, 0, "", -5, -10, 255, 140, NULL, 0, 0, 0, 0, ""); uiDefButBitI(block, TOG, OB_ACTOR, 0, "Sensor actor", xco, yco, 118, 19, &ob->gameflag, 0, 0, 0, 0, @@ -3008,6 +3008,25 @@ static uiBlock *advanced_bullet_menu(void *arg_ob) xco, yco, 118, 19, &ob->margin, 0.0, 1.0, 1, 0, "Collision margin"); } + if (ob->gameflag & OB_SOFT_BODY) { + uiDefButBitI(block, TOG, OB_SOFT_SHAPE_MATCHING, 0, "Shape matching", + xco+=120, yco, 118, 19, &ob->gamesoftFlag, 0, 0, 0, 0, + "Enable soft body shape matching"); + yco -= 25; + xco = 0; + uiDefButF(block, NUMSLI, 0, "LinStiff ", xco, yco, 238, 19, + &ob->linearStiffness, 0.0, 1.0, 1, 0, + "Linear stiffness of the soft body vertex spring"); + yco -= 25; + uiDefButF(block, NUMSLI, 0, "AngStiff ", xco, yco, 238, 19, + &ob->angularStiffness, 0.0, 1.0, 1, 0, + "Angular stiffness of the soft body vertex spring"); + yco -= 25; + uiDefButF(block, NUMSLI, 0, "Volume ", xco, yco, 238, 19, + &ob->volumePreservation, 0.0, 1.0, 1, 0, + "Factor of soft body volume preservation"); + } + uiBlockSetDirection(block, UI_TOP); diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 6c830c7febf..7cc8138cb6f 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -3529,6 +3529,10 @@ void copy_attr(short event) base->object->boundtype = ob->boundtype; } base->object->margin= ob->margin; + base->object->linearStiffness= ob->linearStiffness; + base->object->angularStiffness= ob->angularStiffness; + base->object->volumePreservation= ob->volumePreservation; + base->object->gamesoftFlag= ob->gamesoftFlag; } else if(event==17) { /* tex space */ copy_texture_space(base->object, ob); diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 95693efe30e..3e271be7984 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -797,6 +797,36 @@ static PyObject* gPyGetMaterialType(PyObject*) return PyInt_FromLong(flag); } +static PyObject* gPyDrawLine(PyObject*, PyObject* args) +{ + PyObject* ob_from; + PyObject* ob_to; + PyObject* ob_color; + + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer not available"); + return NULL; + } + + if (!PyArg_ParseTuple(args,"OOO",&ob_from,&ob_to,&ob_color)) + return NULL; + + MT_Vector3 from(0., 0., 0.); + MT_Vector3 to(0., 0., 0.); + MT_Vector3 color(0., 0., 0.); + if (!PyVecTo(ob_from, from)) + return NULL; + if (!PyVecTo(ob_to, to)) + return NULL; + if (!PyVecTo(ob_color, color)) + return NULL; + + gp_Rasterizer->DrawDebugLine(from,to,color); + + Py_RETURN_NONE; +} + + STR_String gPyGetWindowHeight__doc__="getWindowHeight doc"; STR_String gPyGetWindowWidth__doc__="getWindowWidth doc"; STR_String gPyEnableVisibility__doc__="enableVisibility doc"; @@ -838,6 +868,8 @@ static struct PyMethodDef rasterizer_methods[] = { METH_VARARGS, "set the state of a GLSL material setting"}, {"getGLSLMaterialSetting",(PyCFunction) gPyGetGLSLMaterialSetting, METH_VARARGS, "get the state of a GLSL material setting"}, + {"drawLine", (PyCFunction) gPyDrawLine, + METH_VARARGS, "draw a line on the screen"}, { NULL, (PyCFunction) NULL, 0, NULL } }; diff --git a/source/gameengine/PyDoc/Rasterizer.py b/source/gameengine/PyDoc/Rasterizer.py index ebb5332d98d..cdda87fcb49 100644 --- a/source/gameengine/PyDoc/Rasterizer.py +++ b/source/gameengine/PyDoc/Rasterizer.py @@ -181,4 +181,15 @@ def getGLSLMaterialSetting(setting, enable): @type setting: string (lights, shaders, shadows, ramps, nodes, extra_textures) @rtype: boolean """ +def drawLine(from,to,color): + """ + Draw a line in the 3D scene. + + @param from: the origin of the line + @type from: list [x, y, z] + @param to: the end of the line + @type to: list [x, y, z] + @param color: the color of the line + @type color: list [r, g, b] + """ -- cgit v1.2.3 From 718e2bf74f0ba2dcabe5bee7d88c1975ecfe9f06 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Thu, 25 Sep 2008 03:02:30 +0000 Subject: improved game soft bodies, works for objects that are using 'set smooth' use shape matching by default for game soft bodies store soft body index for game vertices --- source/blender/blenkernel/intern/object.c | 2 +- source/blender/blenloader/intern/readfile.c | 1 + .../Converter/BL_BlenderDataConversion.cpp | 7 + source/gameengine/Ketsji/KX_ConvertPhysicsObject.h | 6 + .../gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp | 180 ++++++++++----------- .../Physics/Bullet/CcdPhysicsController.cpp | 100 +++++++++++- .../Physics/Bullet/CcdPhysicsController.h | 10 ++ source/gameengine/Rasterizer/RAS_TexVert.h | 21 ++- 8 files changed, 219 insertions(+), 108 deletions(-) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 54908230d88..9f6921fbade 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -967,7 +967,7 @@ Object *add_only_object(int type, char *name) ob->linearStiffness = 1.0f; ob->angularStiffness = 1.0f; ob->volumePreservation = 1.0f; - ob->gamesoftFlag = 0; + ob->gamesoftFlag = OB_SOFT_SHAPE_MATCHING; /* NT fluid sim defaults */ ob->fluidsimFlag = 0; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index d966d691fdd..f1823de954c 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7853,6 +7853,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) ob->linearStiffness = 1.0f; ob->angularStiffness = 1.0f; ob->volumePreservation = 1.0f; + ob->softflag = OB_SOFT_SHAPE_MATCHING; } } diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 6a5048a9f15..b3df2d7bc85 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1321,6 +1321,13 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, objprop.m_dyna = (blenderobject->gameflag & OB_DYNAMIC) != 0; objprop.m_softbody = (blenderobject->gameflag & OB_SOFT_BODY) != 0; objprop.m_angular_rigidbody = (blenderobject->gameflag & OB_RIGID_BODY) != 0; + + ///for game soft bodies + objprop.m_linearStiffness = blenderobject->linearStiffness; + objprop.m_angularStiffness = blenderobject->angularStiffness; + objprop.m_volumePreservation = blenderobject->volumePreservation; + objprop.m_gamesoftFlag = blenderobject->gamesoftFlag; + objprop.m_ghost = (blenderobject->gameflag & OB_GHOST) != 0; objprop.m_disableSleeping = (blenderobject->gameflag & OB_COLLISION_RESPONSE) != 0;//abuse the OB_COLLISION_RESPONSE flag //mmm, for now, taks this for the size of the dynamicobject diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h index 2b6c2535878..6325c9365fd 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h @@ -87,6 +87,12 @@ struct KX_ObjectProperties bool m_disableSleeping; bool m_hasCompoundChildren; bool m_isCompoundChild; + + float m_linearStiffness; + float m_angularStiffness; + float m_volumePreservation; + int m_gamesoftFlag; + double m_margin; KX_BoundBoxClass m_boundclass; union { diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index c4411a58856..5744a860e92 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -667,6 +667,85 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, #endif //WIN32 + + class KX_SoftBodyDeformer : public RAS_Deformer + { + btSoftBody* m_softBody; + class RAS_MeshObject* m_pMeshObject; + class BL_DeformableGameObject* m_gameobj; + + + public: + KX_SoftBodyDeformer(btSoftBody* softBody,RAS_MeshObject* pMeshObject,BL_DeformableGameObject* gameobj) + : m_softBody(softBody), + m_pMeshObject(pMeshObject), + m_gameobj(gameobj) + { + //printf("KX_SoftBodyDeformer\n"); + }; + + virtual ~KX_SoftBodyDeformer() + { + //printf("~KX_SoftBodyDeformer\n"); + }; + virtual void Relink(GEN_Map*map) + { + //printf("relink\n"); + } + virtual bool Apply(class RAS_IPolyMaterial *polymat) + { + //printf("apply\n"); + RAS_MeshSlot::iterator it; + RAS_MeshMaterial *mmat; + RAS_MeshSlot *slot; + size_t i; + + // update the vertex in m_transverts + Update(); + + // The vertex cache can only be updated for this deformer: + // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object) + // share the same mesh (=the same cache). As the rendering is done per polymaterial + // cycling through the objects, the entire mesh cache cannot be updated in one shot. + mmat = m_pMeshObject->GetMeshMaterial(polymat); + if(!mmat->m_slots[(void*)m_gameobj]) + return true; + + slot = *mmat->m_slots[(void*)m_gameobj]; + + // for each array + for(slot->begin(it); !slot->end(it); slot->next(it)) + { + btSoftBody::tNodeArray& nodes(m_softBody->m_nodes); + + int index = 0; + for(i=it.startvertex; im_ang_drag; //need a bit of damping, else system doesn't behave well ci.m_inertiaFactor = shapeprops->m_inertia/0.4f;//defaults to 0.4, don't want to change behaviour + ci.m_linearStiffness = objprop->m_linearStiffness; + ci.m_angularStiffness= objprop->m_angularStiffness; + ci.m_volumePreservation= objprop->m_volumePreservation; + ci.m_gamesoftFlag = objprop->m_gamesoftFlag; + ci.m_collisionFilterGroup = (isbulletdyna) ? short(CcdConstructionInfo::DefaultFilter) : short(CcdConstructionInfo::StaticFilter); ci.m_collisionFilterMask = (isbulletdyna) ? short(CcdConstructionInfo::AllFilter) : short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::StaticFilter); ci.m_bRigid = objprop->m_dyna && objprop->m_angular_rigidbody; @@ -990,107 +1074,15 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, physicscontroller->SetObject(gameobj->GetSGNode()); - class KX_SoftBodyDeformer : public RAS_Deformer - { - btSoftBody* m_softBody; - class BL_SkinMeshObject* m_pMeshObject; - class BL_DeformableGameObject* m_gameobj; - - - public: - KX_SoftBodyDeformer(btSoftBody* softBody,BL_SkinMeshObject* pMeshObject,BL_DeformableGameObject* gameobj) - : m_softBody(softBody), - m_pMeshObject(pMeshObject), - m_gameobj(gameobj) - { - //printf("KX_SoftBodyDeformer\n"); - }; - - virtual ~KX_SoftBodyDeformer() - { - //printf("~KX_SoftBodyDeformer\n"); - }; - virtual void Relink(GEN_Map*map) - { - //printf("relink\n"); - } - virtual bool Apply(class RAS_IPolyMaterial *polymat) - { - //printf("apply\n"); - RAS_MeshSlot::iterator it; - RAS_MeshMaterial *mmat; - RAS_MeshSlot *slot; - size_t i; - - // update the vertex in m_transverts - Update(); - - // The vertex cache can only be updated for this deformer: - // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object) - // share the same mesh (=the same cache). As the rendering is done per polymaterial - // cycling through the objects, the entire mesh cache cannot be updated in one shot. - mmat = m_pMeshObject->GetMeshMaterial(polymat); - if(!mmat->m_slots[(void*)m_gameobj]) - return true; - - slot = *mmat->m_slots[(void*)m_gameobj]; - - // for each array - for(slot->begin(it); !slot->end(it); slot->next(it)) - { - // for each vertex - // copy the untransformed data from the original mvert - int count = 0; - { - - for(i=it.startvertex; im_nodes); - - if (count == m_softBody->m_userIndexMapping.size()) - { - int index = 0; - for(i=it.startvertex; im_userIndexMapping[index]].m_x.getX(), - nodes[m_softBody->m_userIndexMapping[index]].m_x.getY(), - nodes[m_softBody->m_userIndexMapping[index]].m_x.getZ()); - v.SetXYZ(pt); - - //(m_transverts[v.getOrigIndex()]); - } - } - - } - - return true; - } - virtual bool Update(void) - { - //printf("update\n"); - return true;//?? - } - virtual RAS_Deformer *GetReplica() - { - //printf("getReplica\n"); - return 0; - } - protected: - //class RAS_MeshObject *m_pMesh; - }; ///test for soft bodies if (objprop->m_softbody && physicscontroller) { btSoftBody* softBody = physicscontroller->GetSoftBody(); - if (softBody && gameobj->GetMesh(0)) + if (softBody && gameobj->GetMesh(0))//only the first mesh, if any { //should be a mesh then, so add a soft body deformer - KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer(softBody, (BL_SkinMeshObject*)gameobj->GetMesh(0),(BL_DeformableGameObject*)gameobj); + KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer(softBody, gameobj->GetMesh(0),(BL_DeformableGameObject*)gameobj); gameobj->SetDeformer(softbodyDeformer); } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index ad79db16dc4..333ecd6ea11 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -222,14 +222,57 @@ void CcdPhysicsController::CreateRigidbody() psb->appendFace(idx[0],idx[1],idx[2]); } + ///create a mapping between graphics mesh vertices and soft body vertices { - for (int i=0;im_userIndexMapping.push_back(hlib.m_vertexIndexMapping[i]); - //psb->m_userIndexMapping.push_back(hres.m_Indices[i]); + RAS_MeshObject* rasMesh= GetShapeInfo()->GetMesh(); + + if (rasMesh) + { + + //printf("apply\n"); + RAS_MeshSlot::iterator it; + RAS_MeshMaterial *mmat; + RAS_MeshSlot *slot; + size_t i; + + //for each material + for (int m=0;mNumMaterials();m++) + { + // The vertex cache can only be updated for this deformer: + // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object) + // share the same mesh (=the same cache). As the rendering is done per polymaterial + // cycling through the objects, the entire mesh cache cannot be updated in one shot. + mmat = rasMesh->GetMeshMaterial(m); + + slot = mmat->m_baseslot; + for(slot->begin(it); !slot->end(it); slot->next(it)) + { + int index = 0; + for(i=it.startvertex; isetSoftBodyIndex(0); + btScalar maxDistSqr = 1e30; + btSoftBody::tNodeArray& nodes(psb->m_nodes); + btVector3 xyz = trans(btVector3(vertex->getXYZ()[0],vertex->getXYZ()[1],vertex->getXYZ()[2])); + for (int n=0;nsetSoftBodyIndex(n); + } + } + } + } + } + } } hlib.ReleaseResult(hres); - psb->randomizeConstraints(); + } @@ -292,13 +335,42 @@ void CcdPhysicsController::CreateRigidbody() //psb->m_cfg.collisions = btSoftBody::fCollision::SDF_RS;//btSoftBody::fCollision::CL_SS+ btSoftBody::fCollision::CL_RS; psb->m_cfg.collisions = btSoftBody::fCollision::SDF_RS + btSoftBody::fCollision::CL_SS; + //psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS + btSoftBody::fCollision::CL_RS; //btSoftBody::Material* pm=psb->appendMaterial(); btSoftBody::Material* pm=psb->m_materials[0]; - pm->m_kLST = 0.1f; + + pm->m_kLST = m_cci.m_linearStiffness; + pm->m_kAST = m_cci.m_angularStiffness; + pm->m_kVST = m_cci.m_volumePreservation; + + + + //pm->m_kAST = 0.01f; //pm->m_kVST = 0.001f; psb->generateBendingConstraints(2,pm); + //psb->m_cfg.piterations = 4; + //psb->m_cfg.viterations = 4; + //psb->m_cfg.diterations = 4; + //psb->m_cfg.citerations = 4; + if (m_cci.m_gamesoftFlag & 1)///OB_SOFT_SHAPE_MATCHING) + { + psb->setPose(false,true);// + } else + { + psb->setPose(true,false); + } + + psb->m_cfg.kDF = 0.5; + psb->m_cfg.kMT = 0.05; + psb->m_cfg.piterations = 5; + + psb->m_cfg.piterations = 5; + //psb->m_cfg.kVC = 20; + + psb->randomizeConstraints(); + /* psb->m_cfg.kDF = 0.1f;//1.f; psb->m_cfg.kDP = 0.0001; @@ -315,10 +387,10 @@ void CcdPhysicsController::CreateRigidbody() // psb->activate(); // psb->setActivationState(1); // psb->setDeactivationTime(1.f); - //psb->m_cfg.piterations = 4; + //psb->m_materials[0]->m_kLST = 0.1+(i/(btScalar)(n-1))*0.9; psb->setTotalMass(m_cci.m_mass); - psb->generateClusters(64); + //psb->generateClusters(8);//(64); psb->setCollisionFlags(0); // m_object->setCollisionShape(rbci.m_collisionShape); btTransform startTrans; @@ -1147,7 +1219,19 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope) { const float* vtx = poly->GetVertex(i)->getXYZ(); btPoint3 point(vtx[0],vtx[1],vtx[2]); - m_vertexArray.push_back(point); + //avoid duplicates (could better directly use vertex offsets, rather than a vertex compare) + bool found = false; + for (int j=0;j Date: Thu, 25 Sep 2008 08:41:11 +0000 Subject: binreloc include was wrong for make, removed last YESIAMSTUPID --- source/creator/CMakeLists.txt | 4 ---- source/creator/Makefile | 6 +----- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 93cc0e8afb5..99e8b576412 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -54,10 +54,6 @@ IF(LINUX) INCLUDE_DIRECTORIES(${BINRELOC_INC}) endif(LINUX) -IF(YESIAMSTUPID) - ADD_DEFINITIONS(-DYESIAMSTUPID) -ENDIF(YESIAMSTUPID) - MESSAGE(STATUS "Configuring blender") ADD_CUSTOM_COMMAND( diff --git a/source/creator/Makefile b/source/creator/Makefile index 158aee1a647..9273d943883 100644 --- a/source/creator/Makefile +++ b/source/creator/Makefile @@ -60,11 +60,7 @@ ifeq ($(WITH_QUICKTIME), true) endif ifeq ($(WITH_BINRELOC), true) - CPPFLAGS += -I$(OCGDIR)/extern/binreloc/include -DWITH_BINRELOC -endif - -ifeq ($(NAN_YESIAMSTUPID), true) - CPPFLAGS += -DYESIAMSTUPID + CPPFLAGS += -I$(NANBLENDERHOME)/extern/binreloc/include -DWITH_BINRELOC endif CPPFLAGS += -I$(OPENGL_HEADERS) -- cgit v1.2.3 From c2a202451fec57927d084323cd3364b844aa200a Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Thu, 25 Sep 2008 11:30:39 +0000 Subject: Update of the very ancient 2.3 text of blender.html. Thanks Nathan Letwory for the poke! --- release/text/blender.html | 154 +++++++++++++++++----------------------------- 1 file changed, 55 insertions(+), 99 deletions(-) diff --git a/release/text/blender.html b/release/text/blender.html index c7e88fb7064..30c8f0b0dc2 100644 --- a/release/text/blender.html +++ b/release/text/blender.html @@ -7,7 +7,7 @@ -

Blender v2.3x series

+

Blender v2.4x series


  1. About
  2. @@ -25,19 +25,19 @@

    1. About

    -

    Welcome to the world of Blender! +

    Welcome to the world of Blender! The program you have now in your hands is a free and fully functional 3D -modeling, rendering, animation and game creation suite. It is available for +modeling, animation, rendering, compositing, video editing and game creation suite. It is available for Unix-based (Linux, Mac OS X, etc.) and Windows systems and has a large world-wide community.

    Blender is free to be applied for any purpose, including commercial usage and -distribution. It's open-source software, released under a dual GPL / BL -licence. The full program sources are available online.

    +distribution. It's free and open-source software, released under the GNU GPL +licence. The full program sources are available on our website.

    For impatient readers, here the two most important links:

    -www.blender.org the developement/community website
    -www.blender3d.org the general website
    +www.blender.org the main website
    +wiki.blender.org the documentation website

    back to top

    @@ -58,7 +58,7 @@ plugins and more.

    If you are interested in the development of the program, information for coders and the CVS repository with the sources can be found at the -developer's site.

    +developer's section of the site.

    Installation notes:

    @@ -108,7 +108,7 @@ it's enough to set a system variable called PYTHON to the full path to the stand-alone Python executable (to find out execute "import sys; print sys.executable" inside the stand-alone interpreter, not in Blender). To check which Python was linked to your Blender binary, execute "import sys; print -sys.version" at Blender's text editor), it's probably 2.3.something -- only the +sys.version" at Blender's text editor), it's probably 2.5.something -- only the two first numbers should have to match with yours.

    @@ -130,10 +130,10 @@ Renderman compliant ones. By animating the data and rendering pictures of each successive frame, movie sequences can be created.

    In compositing a set of techniques is used to add effects -to movie strips and combine these into a single video. This is how, for -example, artists add laser beams, glows and dinossaurs to motion -pictures. Blender is not a specific tool for this purpose, but it has builtin -support for video sequencing and sound synchronization.

    +to rendered images and combine these into a single frame. This is how, for +example, artists add laser beams, glows and dinosaurs to motion +pictures. Blender also has builtin +support for video sequence editing and sound synchronization.

    The game engine inside Blender lets users create and play nifty 3d games, complete with 3d graphics, sound, physics and scripted rules. @@ -158,10 +158,10 @@ yourself for your favorite window manager.

    command-line prompt. Try "blender -h" to see all available options.

    Blender saves data in its own custom binary format, using ".blend" as -extension. The default start-up configuration is saved in a file called +extension. The default start-up configuration is saved in a file in your home directory called .B.blend. To save your changes to it, click on File->Save Default Settings or use the Control+u shortcut -directly. To revert to factory defaults, erase the .B.blend file.

    +directly.

    First steps:

    @@ -173,8 +173,7 @@ syndrome, just relax and read this part of the F.A.Q.

    Hoping the explanations helped, let's start Blender and take a look at it. At the top header you can see the main menu. Under "File" you'll find entries to save, load and quit. If someone ever messes with your workspace -and you can't find your way around: press q to quit. Then erase the .B.blend -file in your home dir and the program will be back to factory defaults.

    +and you can't find your way around: use the menu File->Load Factory settings.

    Blender's screen is divided in "areas". Each of them has a top or bottom header and can show any of the available builtin applications (called "spaces", @@ -265,9 +264,8 @@ each space.

    4. Resources

    @@ -276,38 +274,15 @@ each space.

    resources you will need. We can't teach you 3D in these few lines of text, that would take a lengthy book.

    -

    The Blender Foundation has released a new guide, with hundreds of pages of -illustrated tutorials. It comes with a CD-ROM that has Blender version 2.32, -YafRay and many goodies: sample .blend files with models, textures and -animations, plugins, scripts, documentation, etc. It's an extensive reference -written by Blender gurus and also a good way to help Blender development.

    - -

    New: the new guide's text is now available for download -online and the second edition of the printed book has also been released.

    - -

    You can learn more about it at the main Blender site: -www.blender3d.org. There you'll also -find news, online documentation like tutorials, the 2.0 guide, the Blender -Python API Reference for script writers, docs for the newest features added -to the program, etc. There are also forums, galleries of images and movies, -games, scripts, plugins, links for many resources and more.

    - -

    The main Blender community site is elYsiun: -www.elysiun.com. There's a lot of -activity in its user forums, where newbie and guru users share tips and tricks, -show their most recent images, movies and scripts, ask for help and generally -have a good time.

    -

    Irc users are invited to try #blenderchat on irc.freenode.net .

    There are also local Blender community sites in some countries, that should -be listed at the links section of the main site.

    +be listed at the Community section of the main site.

    -

    If you are a coder wanting to get in touch with Blender development, the -developer's site is at www.blender.org. A +

    If you are a coder wanting to get in touch with Blender development, a good read +is the "Get Involved" page at www.blender.org. A good way to start is to follow the mailing lists for a while and check bug -reports, to see if you can fix one. On irc.freenode.net: #blendersauce (open channel) -and #blendercoders (official channel, where also meetings take place).

    +reports, to see if you can fix one. On irc.freenode.net: #blendercoders you'll find many active developers, here also the weekly meetings take place.

    Other useful links

    @@ -324,17 +299,14 @@ resource to create, convert and, of course, manipulate texture images. It is also useful for work with rendered pictures, for example to add 2d text, logos or to touch-up, apply factory or hand-made effects and compose with other images. -
    The Wings 3D modeler
    -
    A great mesh modeler, with a different approach. Some things are much -easier to model in Wings, others in Blender, making them a powerful combination -for experienced users.
    +

    Renderers:

    YafRay
    -
    A relatively new and already very impressive program. Blender has builtin +
    A currently inactive but very impressive program. Blender has builtin support for it.
    Povray
    One of the best and most popular renderers in the world. There is a @@ -384,19 +356,8 @@ buttons and pulldown menus. That means also the 2D options for OpenGL should work good, something easily ignored or badly tested by 3D card manufacturors, who target more at the latest SFX features for new 3D games.
    In general Blender performs -very well on 3D cards from renowned brands, such as NVidia, ATI or 3DLabs. Recently -however, new drivers (especially for ATI) have shown that they're dropping basic -OpenGL support needed for proper menu drawing in Blender. Downgrading drivers then -always works, but we're also working on rebuilding the (quite old) code for GUI -drawing to prevent such errors from ever happening again.

    - -

    Some useful links to check:
    +very well on 3D cards from renowned brands, such as NVidia, ATI or 3DLabs.

    -The graphics card FAQ
    -3D card performance database
    - - -

    Scripts

    @@ -407,7 +368,7 @@ one of the submenus there, it refers to a script. Please don't report problems with scripts to the bug tracker or other normal Blender channels. You should find the author's site or contact email in the script's text itself, but usually the Python & Plugins forum at -elYsiun is used for posting +Blenderartists.org is used for posting announcements, questions, suggestions and bug reports related to scripts. It's the recommended place to look first, specially if no site was specified at the script's window or source file(s).

    @@ -444,8 +405,8 @@ black rectangle.

    Setting texture map input to "uv" in the Material Buttons window is not enough to assign a texture image and uv data to a mesh. It's necessary to select the mesh, -enter face select mode (modes can be accessed in the 3d view's header), load an -image in the UV/Image Editor window and then define the mapping. Only then +enter edit mode, indicate face selection mode (modes can be accessed in the 3d view's header), load an +image in the UV/Image Editor window and then define a mapping (or unwrapping). Only then the mesh will have uv data available for exporting.

    If you want the fastest possible access to Blender's functionality, remember @@ -455,23 +416,24 @@ workspace to your needs.

    What's up with the interface?

    -

    Blender does not follow the most common, somewhat standard rules for user -interfaces -- it doesn't look like most programs do -- which is not necessarily -a bad thing. There used to be two sides to this: Blender was both a powerful -production tool for professionals and enthusiasts who dedicated enough time to -master it and also a nightmare for some newcomers who might have tried one of -the commercial 3d modelers first. The main reason for this is that -Blender was born as an in-house studio tool, optimized to speed up daily heavy -work, not to please everyone. But it's true that in the past the interface -was far from newbie-friendly.

    - -

    Hopefully this is not the case anymore: it has been considerably -improved for the 2.3x series, exposing most functionality via menus, adding +

    Blender uses a couple of innovative paradigms in the UI, not following more common, somewhat standard rules for user +interfaces. In the past years several of our interface concepts have been adopted in more programs though, +especially using a configurable non-overlapping subdivision layout and the paradigm to never block the UI from working by +offering all editors and options in parallel.
    +Typically free programs offer easy-to-use interfaces for large audiences. Blender however is, like other high-end 3D tools, +meant to be a powerful production tool for professionals and 3D enthusiasts, for people who are dedicated to become 3D artists with enough time +and motivation to master the software.
    +This also has its origins in the 90ies, when Blender was born as an in-house studio tool, optimized to speed up daily heavy +work, and not to please everyone. But it's true that you can consider Blender's interface +to be not very newbie-friendly. Luckily you only have to learn it once, and once you get the basics it'll feel like 2nd nature!

    + +

    Blender also has been considerably +improved since the 2.3x series, exposing most functionality via menus, adding panels, color "themability", tooltips for all buttons and internationalization support. This is an ongoing effort or, better, a goal to keep the best ideas in Blender's design while expanding and making it more user-friendly.

    -

    Too many buttons!

    +

    Too many buttons!

    Again, 3D Computer Graphics is a vast and fun field. If you're only starting, Blender can seem daunting, specially because of all its packed @@ -503,38 +465,39 @@ play with. A few more months and you'll probably be back asking for more ...

    If you ever get the impression that it's not possible to create great looking or complex works with Blender, rejoice -- you are just plainly -uninformed, as browsing galleries and community forums can easily confirm.

    +uninformed, as browsing blender.org galleries and community forums can easily confirm.

    How does it compare to other 3d programs?

    In short: it takes considerable dedication to become good, no matter which program you work with, as long as it is good enough not to get in your way. -Blender is. And, like the others, has strong and weak points.

    +Blender has, like the others, its strong and weak points.

    Compared to commercial alternatives, Blender misses some features and isn't as "newbie-friendly". It doesn't come packed with "one-click" or "wizard" functionality, where you get much faster results in detriment of flexibility and value. It also isn't bundled with tens of megabytes of sample models, texture images, tutorials, etc. (which only partly explains how Blender can fit -in a less than 4 MB download).

    +in such a small download).

    -

    Thankfully, these are not fatal shortcomings. The pace at which features +

    Thankfully, these are relatively minor shortcomings. Many of Blender's modeling, animation and +rendering/compositing features are up-to-par with the industry standards. The pace at which features are being added or polished in Blender is impressive, now that it's a well -stablished open source project. More: through plugins and scripting, many +stablished open source project. We get daily feedback from professionals and studios using Blender, and +results from the Blender Foundation's Open Movie/Game projects such as Big Buck Bunny +and Yo Frankie! have set a reference standard for what a program like Blender can achieve. + More: through plugins and scripting, many repetitive or otherwise cumbersome tasks can be made trivial. But plugin and script authors go further, teaching Blender new tricks, from importers and exporters to more advanced "applications".

    About goodies, there are many places where you can get them (check -resources). Besides the book, the main site and -elYsiun are the best ones to start, specially because some resources you -find spread on the net are not up-to-date with current program versions. This -doesn't render old tutorials or books useless -- just a little harder to -follow, sometimes -- but older scripts probably won't work. For free texture +resources). Besides the many available Blender books, the main site and +blenderartists.org are the best ones to start. For free texture images, a simple search for "free textures" should bring many results, just pay attention to their licenses if you plan to release your work later.

    -

    Commercial packages can make it easier for newbies to produce nice looking +

    Commercial packages might make it easier for newbies to produce nice looking material, but only another newbie would praise the results. There's a huge difference between what a skilled artist and someone poking at buttons and using presets can accomplish.

    @@ -542,17 +505,10 @@ using presets can accomplish.

    Last but best of all: Blender is open-source, free for all to use, study and improve.

    - -

    Something doesn't work, what do I do?

    - -

    First note again that errors and questions related to specific scripts -should not be sent to Blender developers or its bug tracker. Then -read this short section thoroughly, please.

    -

    Thanks for reading, we hope you enjoy Blender!

    -

    Document version 1.01, June 2004

    +

    Document version 1.1, Sept 2008

    back to top

    -- cgit v1.2.3 From 2b6f6698d294c2d586457dda6a3f460f4677c88c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 25 Sep 2008 13:17:56 +0000 Subject: patch [#17683] Fix OBJ import line endings from Tom Nixon (greysquare) for fixing [#17681] .OBj import issues --- release/scripts/import_obj.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/release/scripts/import_obj.py b/release/scripts/import_obj.py index b467cca112f..6ddfb867a36 100644 --- a/release/scripts/import_obj.py +++ b/release/scripts/import_obj.py @@ -182,7 +182,7 @@ def create_materials(filepath, material_libs, unique_materials, unique_material_ else: #print '\t\tloading mtl: "%s"' % mtlpath context_material= None - mtl= open(mtlpath) + mtl= open(mtlpath, 'rU') for line in mtl: #.xreadlines(): if line.startswith('newmtl'): context_material_name= line_value(line.split()) @@ -194,7 +194,7 @@ def create_materials(filepath, material_libs, unique_materials, unique_material_ elif context_material: # we need to make a material to assign properties to it. line_split= line.split() - line_lower= line.lower() + line_lower= line.lower().lstrip() if line_lower.startswith('ka'): context_material.setMirCol((float(line_split[1]), float(line_split[2]), float(line_split[3]))) elif line_lower.startswith('kd'): @@ -588,7 +588,7 @@ def load_obj(filepath, CLAMP_SIZE= 0.0, CREATE_FGONS= True, CREATE_SMOOTH_GROUPS print '\tpassing obj file "%s"...' % filepath, time_sub= sys.time() - file= open(filepath, 'r') + file= open(filepath, 'rU') for line in file: #.xreadlines(): if line.startswith('v '): @@ -859,7 +859,7 @@ else: os.system('find /fe/obj -iname "*.obj" > /tmp/temp3ds_list') print '...Done' - file= open('/tmp/temp3ds_list', 'r') + file= open('/tmp/temp3ds_list', 'rU') lines= file.readlines() file.close() -- cgit v1.2.3 From 1722aeb6ea53939f96c2447e7facc58d9d324a52 Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Thu, 25 Sep 2008 15:39:46 +0000 Subject: This is part of the cleanup Campbell wanted :) Just getting rid of license_key stuff. The project files still need to be updated: projectfiles_vc7/blender/src/BL_src_cre.vcproj projectfiles_vc7/blender/blendercompactNG.vcproj Just search for these files in them. Kent --- intern/SoundSystem/intern/SND_Utils.cpp | 5 - source/blender/include/license_key.h | 92 ------- source/blender/src/cre/license.jpeg.c | 35 --- source/blender/src/cre/license_key.c | 194 -------------- source/blender/src/pub/license_key.c | 444 -------------------------------- 5 files changed, 770 deletions(-) delete mode 100644 source/blender/include/license_key.h delete mode 100644 source/blender/src/cre/license.jpeg.c delete mode 100644 source/blender/src/cre/license_key.c delete mode 100644 source/blender/src/pub/license_key.c diff --git a/intern/SoundSystem/intern/SND_Utils.cpp b/intern/SoundSystem/intern/SND_Utils.cpp index 7d441964b24..05101a7e6e6 100644 --- a/intern/SoundSystem/intern/SND_Utils.cpp +++ b/intern/SoundSystem/intern/SND_Utils.cpp @@ -34,11 +34,6 @@ #include "SND_Utils.h" #include "SoundDefines.h" #include "SND_DependKludge.h" -/* -extern "C" { -#include "license_key.h" -} -*/ #include #include #include diff --git a/source/blender/include/license_key.h b/source/blender/include/license_key.h deleted file mode 100644 index 7dc14f45e74..00000000000 --- a/source/blender/include/license_key.h +++ /dev/null @@ -1,92 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef LICENCEKEY_H -#define LICENCEKEY_H - -#define I_AM_PUBLISHER temp_val2 -#define LICENSE_KEY_VALID temp_val -#define SHOW_LICENSE_KEY rotop - -extern int LICENSE_KEY_VALID; -extern int I_AM_PUBLISHER; - -extern char * license_key_name; -extern void loadKeyboard(char * name); -extern void checkhome(void); -extern void SHOW_LICENSE_KEY(void); - -#define LICENSE_CHECK_0 (0==0) - -// Stuff from the Python files from Strubi - -typedef int (*Fptr)(void *); - -extern Fptr g_functab[]; -extern Fptr g_ptrtab[]; - -// TODO: From here on, this should be a generated header file... - -// change all KEY_FUNC values -// if you change PYKEY_TABLEN or PYKEY_SEED -// see below - -#define PYKEY_TABLEN 21 // don't change this unless needed. Other values - // may yield bad random orders - -#define PYKEY_SEED {26,8,1972} - -// these values are generated by $HOME/develop/intern/keymaker/makeseed.py -// from the above seed value. - -// DO NOT EDIT THESE VALUES BY HAND! - -#define KEY_FUNC1 12 -#define KEY_FUNC2 8 -#define KEY_FUNC3 1 -#define KEY_FUNC4 16 -#define KEY_FUNC5 20 -#define KEY_FUNC6 18 -#define KEY_FUNC7 13 -#define KEY_FUNC8 6 -#define KEY_FUNC9 9 -#define KEY_FUNC10 7 -#define KEY_FUNC11 14 -#define KEY_FUNC12 0 -#define KEY_FUNC13 5 -#define KEY_FUNC14 10 -#define KEY_FUNC15 19 -#define KEY_FUNC16 2 -#define KEY_FUNC17 11 -#define KEY_FUNC18 3 -#define KEY_FUNC19 17 -#define KEY_FUNC20 15 -#define KEY_FUNC21 4 - -#endif - diff --git a/source/blender/src/cre/license.jpeg.c b/source/blender/src/cre/license.jpeg.c deleted file mode 100644 index 6d8f0e3da9d..00000000000 --- a/source/blender/src/cre/license.jpeg.c +++ /dev/null @@ -1,35 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -int datatoc_tonize= 0; -char datatoc_ton[]= {0}; diff --git a/source/blender/src/cre/license_key.c b/source/blender/src/cre/license_key.c deleted file mode 100644 index 37b67d44bb6..00000000000 --- a/source/blender/src/cre/license_key.c +++ /dev/null @@ -1,194 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include "license_key.h" -#include "keyed_functions.h" -#include "BKE_utildefines.h" -#include "BIF_screen.h" // splash -#include "BIF_toolbox.h" -#include -#include -#include "BLO_readfile.h" -//#include "BLO_keyStore.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -int LICENSE_KEY_VALID = TRUE; -int I_AM_PUBLISHER = TRUE; - -// Python stuff - -#include "Python.h" -#include "marshal.h" -#include "compile.h" /* to give us PyCodeObject */ -#include "eval.h" /* prototype for PyEval_EvalCode */ - -#include "BPY_extern.h" -#include "IMB_imbuf.h" - -Fptr g_functab[PYKEY_TABLEN]; -Fptr g_ptrtab[PYKEY_TABLEN]; - -static int g_seed[3] = PYKEY_SEED; -static PyObject *g_module_self; -static PyObject *g_main; - - -// end Python stuff - -// **************** PYTHON STUFF ************************** -/* ----------------------------------------------------- */ -/* this is the dummy functions to demonstrate */ - -int sticky_shoes(void *vp) -{ -#ifndef NDEBUG - printf("feature not enabled: Buy our Key NOW!\n"); -#endif - return 0; -} - -/* -int key_func1(void *vp) { - printf("function 1 called\n"); -} - -*/ -int key_return_true(void *vp) { -#ifndef NDEBUG - printf("function 2 called (return true)\n"); -#endif - return 1; -} - -/* ----------------------------------------------------- */ - -/* Declarations for objects of type Fplist */ - - -#ifndef NDEBUG -void feature1(void) -{ - Fptr f; - - printf("feature 2 called\n"); - f = g_ptrtab[KEY_FUNC2]; - if (f) f(0); -} - -void feature2(void) -{ - Fptr f; - - printf("feature 3 called\n"); - f = g_ptrtab[KEY_FUNC3]; - if (f) f(0); -} - -#endif - - -/* Initialization function for the module (*must* be called initprot) */ - -static void init_ftable(void) // initializes functiontable -{ - int i; - - g_functab[0] = &key_func1; - - for (i = 1; i < PYKEY_TABLEN; i++) - { - g_functab[i] = &sticky_shoes; - } - - // for debugging perposes - /* - for (i = 0; i < PYKEY_TABLEN; i++) - { - g_functab[i] = (Fptr *) (i + 100); - } - */ -} - - -static void init_ptable(void) // initializes functiontable -{ - int i; - - for (i = 0; i < PYKEY_TABLEN; i++) - { - g_ptrtab[i] = &sticky_shoes; - } -} - - -#ifdef NDEBUG -static void print_ptable(void) -{ - int i; - - for (i = 0; i < PYKEY_TABLEN; i++) - { - printf ("index[%02d] = %08x\n", i, g_ptrtab[i]); - } -} -#endif - -static void insertname(PyObject *m,PyObject *p, char *name) -{ -} - -/* initialisation */ -static void initprot() -{ - init_ftable(); // malloc - init_ptable(); // malloc -} - -// ******************************* KEY STUFF ********************* - -void create_key_name(char * keyname) -{ -} - -void checkhome() -{ - initprot(); // initialize module and function tables - -} - -void SHOW_LICENSE_KEY(void) -{ -} - -void loadKeyboard(char * name) -{ -} diff --git a/source/blender/src/pub/license_key.c b/source/blender/src/pub/license_key.c deleted file mode 100644 index 3b825f35743..00000000000 --- a/source/blender/src/pub/license_key.c +++ /dev/null @@ -1,444 +0,0 @@ -/** - * $Id$ - * - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#include "license_key.h" -#include "keyed_functions.h" -#include "BKE_utildefines.h" -#include "BIF_screen.h" // splash -#include "BIF_toolbox.h" -#include "blenkey.h" -#include -#include - -#include "BLI_blenlib.h" - -#include "BLO_readfile.h" -#include "BLO_keyStore.h" - -#ifdef HAVE_CONFIG_H -#include -#endif - -int LICENSE_KEY_VALID = TRUE; -int I_AM_PUBLISHER = TRUE; - -static UserStruct User; - -// Python stuff - -#include "Python.h" -#include "marshal.h" -#include "compile.h" /* to give us PyCodeObject */ -#include "eval.h" /* prototype for PyEval_EvalCode */ - -#include "BPY_extern.h" - -#include "IMB_imbuf.h" - -Fptr g_functab[PYKEY_TABLEN]; -Fptr g_ptrtab[PYKEY_TABLEN]; - -static int g_seed[3] = PYKEY_SEED; -static PyObject *g_module_self; -static PyObject *g_main; - - -// end Python stuff - -// **************** PYTHON STUFF ************************** -/* ----------------------------------------------------- */ -/* this is the dummy functions to demonstrate */ - -int sticky_shoes(void *vp) -{ - return 0; -} - -/* -int key_func1(void *vp) { - printf("function 1 called\n"); -} - -*/ -int key_return_true(void *vp) { - return 1; -} - - -/* ----------------------------------------------------- */ - -/* Declarations for objects of type Fplist */ - - -static char prot_getseed__doc__[] = ""; - -static PyObject * -prot_getseed(self, args) - PyObject *self; /* Not used */ - PyObject *args; -{ - PyObject *p; - p = PyTuple_New(3); - PyTuple_SetItem(p, 0, PyInt_FromLong(g_seed[0])); - PyTuple_SetItem(p, 1, PyInt_FromLong(g_seed[1])); - PyTuple_SetItem(p, 2, PyInt_FromLong(g_seed[2])); - return p; -} - -static char prot_getlen__doc__[] = ""; -static PyObject * -prot_getlen(self, args) - PyObject *self; /* Not used */ - PyObject *args; -{ - return Py_BuildValue("i", PYKEY_TABLEN); -} - -static char prot_getptr__doc__[] = -"" -; - -static PyObject * -prot_getptr(self, args) - PyObject *self; /* Not used */ - PyObject *args; -{ - PyObject *p; - Fptr f; - int index; - /* we don't catch errors here, we're in the key code */ - if (!g_functab) - return NULL; - if (!PyArg_ParseTuple(args, "i", &index)) - return NULL; - if (index >= PYKEY_TABLEN) - return NULL; - - f = g_functab[index]; - p = PyCObject_FromVoidPtr(f , NULL); - return p; -} - -static char prot_setptr__doc__[] = -"" -; -static PyObject * -prot_setptr(self, args) - PyObject *self; /* Not used */ - PyObject *args; -{ - PyObject *p; - - int index; - - if (!g_ptrtab) - return NULL; - if (!PyArg_ParseTuple(args, "iO", &index, &p)) - return NULL; - if (index >= PYKEY_TABLEN) - return NULL; - if (!PyCObject_Check(p)) { - return NULL; - } - - g_ptrtab[index] = PyCObject_AsVoidPtr(p); - return Py_BuildValue("i", 1); -} - -static PyObject *callkeycode( - unsigned char *keycode, - int keycodelen) -{ - PyCodeObject *code; - PyObject *maindict = PyModule_GetDict(g_main); - - code = (PyCodeObject *) PyMarshal_ReadObjectFromString(keycode, keycodelen); - if (!PyEval_EvalCode(code, maindict, maindict)) - return NULL; - return Py_BuildValue("i", 1); -} - - - -/* List of methods defined in the module */ - -static struct PyMethodDef prot_methods[] = { - {"getlen", (PyCFunction)prot_getlen, METH_VARARGS, prot_getlen__doc__}, - {"getseed", (PyCFunction)prot_getseed, METH_VARARGS, prot_getseed__doc__}, - {"getptr", (PyCFunction)prot_getptr, METH_VARARGS, prot_getptr__doc__}, - {"setptr", (PyCFunction)prot_setptr, METH_VARARGS, prot_setptr__doc__}, - - {NULL, (PyCFunction)NULL, 0, NULL} /* sentinel */ -}; - - -/* Initialization function for the module (*must* be called initprot) */ - -static char prot_module_documentation[] = "No Documentation"; - -static void init_ftable(void) // initializes functiontable -{ - int i; - - g_functab[0] = &key_func1; -/* add more key_funcs here */ - - for (i = 1; i < PYKEY_TABLEN; i++) - { - g_functab[i] = &sticky_shoes; - } -} - - -static void init_ptable(void) // initializes functiontable -{ - int i; - - for (i = 0; i < PYKEY_TABLEN; i++) - { - g_ptrtab[i] = &sticky_shoes; - } -} - - -static void insertname(PyObject *m,PyObject *p, char *name) -{ - PyObject *d = PyModule_GetDict(m); - - EXPP_dict_set_item_str(d, name, p); -} - -/* initialisation */ -static void initprot() -{ - PyObject *m, *d; - PyObject *capi1; - init_ftable(); - - g_main = PyImport_AddModule("__main__"); - - m = Py_InitModule4("prot", prot_methods, - prot_module_documentation, - (PyObject*)NULL,PYTHON_API_VERSION); - g_module_self = m; - d = PyModule_GetDict(m); - EXPP_dict_set_item_str(d, "error", PyString_FromString("prot.error"); - - /* add global object */ - - capi1 = PyCObject_FromVoidPtr((void *)g_functab , NULL); - if (capi1) { - insertname(m, capi1, "APIfunctab"); - } - - /* Check for errors */ - if (PyErr_Occurred()) - Py_FatalError("can't initialize module prot"); - - init_ptable(); -} - -// ******************************* KEY STUFF ********************* - -static void create_key_name(char * keyname) -{ - sprintf(keyname, "%s/.BPkey", BLI_gethome()); -} - -void checkhome() -{ - int keyresult; - char *HexPriv, *HexPub, *HexPython; - byte *Byte; - char keyname[FILE_MAXDIR + FILE_MAXFILE]; - int wasInitialized; - unsigned char *keycode = NULL; - int keycodelen = 0; - - create_key_name(keyname); - keyresult = ReadKeyFile(keyname, &User, &HexPriv, &HexPub, - &Byte, &HexPython); - if (keyresult != 0) { - // printf("\nReadKeyFile error %d\n", keyresult); - } else { - // printf("\nReadKeyFile OK\n"); - LICENSE_KEY_VALID = TRUE; - - wasInitialized = Py_IsInitialized(); - - // make it failsafe if python interpreter was already initialized - if (wasInitialized) - Py_Initialize(); - - initprot(); // initialize module and function tables - // get python byte code - keycode = DeHexify(HexPython); - keycodelen = strlen(HexPython) / 2; - - callkeycode(keycode, keycodelen); - - Py_Finalize(); - - if (wasInitialized) // if we were initialized, - BPY_start_python(); // restart creator python - - //some debugging stuff - // print_ptable(); - - // Store key stuff for use by stream - keyStoreConstructor( - &User, - HexPriv, - HexPub, - Byte, - HexPython); - - // other initialization code - - } -} - -void SHOW_LICENSE_KEY(void) -{ - extern int datatoc_tonize; - extern char datatoc_ton[]; - char string[1024]; - int maxtype, type; - char *typestrings[] = { - "", - "Individual", - "Company", - "Unlimited", - "Educational"}; - - maxtype = (sizeof(typestrings) / sizeof(char *)) - 1; - type = User.keytype; - if (type > maxtype) { - type = 0; - } - - if (LICENSE_KEY_VALID) { - sprintf(string, "%s License registered to: %s (%s)", typestrings[type], User.name, User.email); - splash((void *)datatoc_ton, datatoc_tonize, string); - } -} - -void loadKeyboard(char * name) -{ - char keyname[FILE_MAXDIR + FILE_MAXFILE]; - FILE *in, *out; - char string[1024], *match = 0; - int i, c; - int found = 0; - - // make sure we don't overwrite a valid key... - - if (!LICENSE_KEY_VALID) { - in = fopen(name, "rb"); - if (in) { - // scan for blender key magic, read strings - // with anything but a newline - while (fscanf(in, "%1000[^\n\r]", string) != EOF) { - match = strstr(string, BLENKEYMAGIC); - if (match) { - break; - } - fscanf(in, "\n"); - } - - if (match) { - // found blender key magic, open output file - // to copy key information - - create_key_name(keyname); - out = fopen(keyname, "wb"); - if (out) { - // printout first line - fprintf(out, "%s", match); - for (i = 0; i < 350; i++) { - // handle control characters (\n\r) - while (1) { - c = getc(in); - if (c == '\n') { - // output a \n for each \n in the input - fprintf(out, "\n"); - } else if (c == EOF) { - break; - } else if (c < ' ') { - // skip control characters - } else { - ungetc(c, in); - break; - } - } - - if (fscanf(in, "%1000[^\n\r]", string) != EOF) { - if (strcmp(string, BLENKEYSEPERATOR) == 0) { - found++; - } - fprintf(out, "%s", string); - } else { - break; - } - - if (found >= 2) { - break; - } - } - - fclose(out); - - checkhome(); - if (LICENSE_KEY_VALID) { - SHOW_LICENSE_KEY(); - } else { - error("Not a valid license key ! Removing installed key."); - BLI_delete(keyname, 0, 0); - } - - } else { - error("Can't install key"); - } - } else { - error("File doesn't contain a valid key: %s", name); - } - - fclose(in); - - if (LICENSE_KEY_VALID) { - if (okee("Remove input file: '%s'?", name)) { - BLI_delete(name, 0, 0); - } - } - - } else { - error("File doesn't exist: %s", name); - } - } -} -- cgit v1.2.3 From 04fa0fd8692dcf402d212245293f5082bb08d630 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Thu, 25 Sep 2008 16:13:17 +0000 Subject: Update MSVC project files for blenderplayer --- projectfiles_vc7/gameengine/gameplayer/common/GP_common.vcproj | 8 ++++---- projectfiles_vc7/gameengine/gameplayer/ghost/GP_ghost.vcproj | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/projectfiles_vc7/gameengine/gameplayer/common/GP_common.vcproj b/projectfiles_vc7/gameengine/gameplayer/common/GP_common.vcproj index 223a1187347..4d2e375f328 100644 --- a/projectfiles_vc7/gameengine/gameplayer/common/GP_common.vcproj +++ b/projectfiles_vc7/gameengine/gameplayer/common/GP_common.vcproj @@ -21,7 +21,7 @@ Date: Thu, 25 Sep 2008 16:19:07 +0000 Subject: BGE patch: add Debug button next to object state. The object state mask will be printed at runtime with the debug info as a comma separated list of state numbers (1..30) for each active state bit. The reserved property name __state__ is used for that purpose (users should not create a property with that name). --- source/blender/makesdna/DNA_object_types.h | 1 + source/blender/src/buttons_logic.c | 11 ++--- .../gameengine/Converter/KX_ConvertProperties.cpp | 8 +++- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 48 ++++++++++++++++++---- 4 files changed, 52 insertions(+), 16 deletions(-) diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 041e0eaebde..2fed5e6170b 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -469,6 +469,7 @@ extern Object workob; #define OB_SHOWCONT 2048 #define OB_SETSTBIT 4096 #define OB_INITSTBIT 8192 +#define OB_DEBUGSTATE 16384 /* ob->restrictflag */ #define OB_RESTRICT_VIEW 1 diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 667f822bed5..dd374af8675 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -3366,24 +3366,25 @@ void logic_buts(void) /* first show the state */ uiBlockSetEmboss(block, UI_EMBOSSP); - uiDefBlockBut(block, object_state_mask_menu, ob, "State", (short)(xco-10), (short)(yco-10), 40, 19, "Object state menu: store and retrieve initial state"); + uiDefBlockBut(block, object_state_mask_menu, ob, "State", (short)(xco-10), (short)(yco-10), 36, 19, "Object state menu: store and retrieve initial state"); uiBlockSetEmboss(block, UI_EMBOSS); if (!ob->state) ob->state = 1; for (offset=0; offset<15; offset+=5) { uiBlockBeginAlign(block); for (stbit=0; stbit<5; stbit++) { - but = uiDefButBitI(block, controller_state_mask&(1<<(stbit+offset)) ? BUT_TOGDUAL:TOG, 1<<(stbit+offset), stbit+offset, "", (short)(xco+35+12*stbit+13*offset), yco, 12, 12, (int *)&(ob->state), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+offset))); + but = uiDefButBitI(block, controller_state_mask&(1<<(stbit+offset)) ? BUT_TOGDUAL:TOG, 1<<(stbit+offset), stbit+offset, "", (short)(xco+31+12*stbit+13*offset), yco, 12, 12, (int *)&(ob->state), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+offset))); uiButSetFunc(but, check_state_mask, but, &(ob->state)); } for (stbit=0; stbit<5; stbit++) { - but = uiDefButBitI(block, controller_state_mask&(1<<(stbit+offset+15)) ? BUT_TOGDUAL:TOG, 1<<(stbit+offset+15), stbit+offset+15, "", (short)(xco+35+12*stbit+13*offset), yco-12, 12, 12, (int *)&(ob->state), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+offset+15))); + but = uiDefButBitI(block, controller_state_mask&(1<<(stbit+offset+15)) ? BUT_TOGDUAL:TOG, 1<<(stbit+offset+15), stbit+offset+15, "", (short)(xco+31+12*stbit+13*offset), yco-12, 12, 12, (int *)&(ob->state), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+offset+15))); uiButSetFunc(but, check_state_mask, but, &(ob->state)); } } uiBlockBeginAlign(block); - uiDefButBitS(block, TOG, OB_SETSTBIT, B_SET_STATE_BIT, "All",(short)(xco+235), yco-10, 25, 19, &ob->scaflag, 0, 0, 0, 0, "Set all state bits"); - uiDefButBitS(block, TOG, OB_INITSTBIT, B_INIT_STATE_BIT, "Ini",(short)(xco+260), yco-10, 25, 19, &ob->scaflag, 0, 0, 0, 0, "Set the initial state"); + uiDefButBitS(block, TOG, OB_SETSTBIT, B_SET_STATE_BIT, "All",(short)(xco+226), yco-10, 22, 19, &ob->scaflag, 0, 0, 0, 0, "Set all state bits"); + uiDefButBitS(block, TOG, OB_INITSTBIT, B_INIT_STATE_BIT, "Ini",(short)(xco+248), yco-10, 22, 19, &ob->scaflag, 0, 0, 0, 0, "Set the initial state"); + uiDefButBitS(block, TOG, OB_DEBUGSTATE, 0, "D",(short)(xco+270), yco-10, 15, 19, &ob->scaflag, 0, 0, 0, 0, "Print state debug info"); uiBlockEndAlign(block); yco-=35; diff --git a/source/gameengine/Converter/KX_ConvertProperties.cpp b/source/gameengine/Converter/KX_ConvertProperties.cpp index aae8752671f..dfbc6f0c48d 100644 --- a/source/gameengine/Converter/KX_ConvertProperties.cpp +++ b/source/gameengine/Converter/KX_ConvertProperties.cpp @@ -132,6 +132,10 @@ void BL_ConvertProperties(Object* object,KX_GameObject* gameobj,SCA_TimeEventMan prop = prop->next; } - - + // check if state needs to be debugged + if (object->scaflag & OB_DEBUGSTATE) + { + // reserve name for object state + scene->AddDebugProperty(gameobj,STR_String("__state__")); + } } diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index c7b0d7b3ea3..b1ab8e3e7de 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -1243,19 +1243,49 @@ void KX_KetsjiEngine::RenderDebugProperties() CValue* propobj = (*it)->m_obj; STR_String objname = propobj->GetName(); STR_String propname = (*it)->m_name; - CValue* propval = propobj->GetProperty(propname); - if (propval) + if (propname == "__state__") { - STR_String text = propval->GetText(); - debugtxt = objname + "." + propname + " = " + text; + // reserve name for object state + KX_GameObject* gameobj = static_cast(propobj); + unsigned int state = gameobj->GetState(); + debugtxt = objname + "." + propname + " = "; + bool first = true; + for (int statenum=1;state;state >>= 1, statenum++) + { + if (state & 1) + { + if (!first) + { + debugtxt += ","; + } + debugtxt += STR_String(statenum); + first = false; + } + } m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, - debugtxt.Ptr(), - xcoord, - ycoord, - m_canvas->GetWidth(), - m_canvas->GetHeight()); + debugtxt.Ptr(), + xcoord, + ycoord, + m_canvas->GetWidth(), + m_canvas->GetHeight()); ycoord += 14; } + else + { + CValue* propval = propobj->GetProperty(propname); + if (propval) + { + STR_String text = propval->GetText(); + debugtxt = objname + "." + propname + " = " + text; + m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, + debugtxt.Ptr(), + xcoord, + ycoord, + m_canvas->GetWidth(), + m_canvas->GetHeight()); + ycoord += 14; + } + } } } } -- cgit v1.2.3 From bc28feb997b05d61d2d1e971137be489c780dcbc Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Thu, 25 Sep 2008 16:48:25 +0000 Subject: re-use some Blender soft body settings for Bullet game soft bodies --- source/blender/blenkernel/intern/object.c | 6 +- source/blender/blenloader/intern/readfile.c | 4 -- source/blender/makesdna/DNA_object_types.h | 9 --- source/blender/src/buttons_logic.c | 68 ++++++++++++++-------- source/blender/src/editobject.c | 8 +-- .../Converter/BL_BlenderDataConversion.cpp | 19 ++++-- .../Physics/Bullet/CcdPhysicsController.cpp | 5 +- 7 files changed, 66 insertions(+), 53 deletions(-) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 9f6921fbade..7b53d770861 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -964,11 +964,7 @@ Object *add_only_object(int type, char *name) ob->anisotropicFriction[2] = 1.0f; ob->gameflag= OB_PROP|OB_COLLISION; ob->margin = 0.0; - ob->linearStiffness = 1.0f; - ob->angularStiffness = 1.0f; - ob->volumePreservation = 1.0f; - ob->gamesoftFlag = OB_SOFT_SHAPE_MATCHING; - + /* NT fluid sim defaults */ ob->fluidsimFlag = 0; ob->fluidsimSettings = NULL; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index f1823de954c..66905c6f240 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7850,10 +7850,6 @@ static void do_versions(FileData *fd, Library *lib, Main *main) if (!(ob->gameflag & OB_ACTOR)) ob->gameflag &= ~(OB_GHOST|OB_DYNAMIC|OB_RIGID_BODY|OB_SOFT_BODY|OB_COLLISION_RESPONSE); /* suitable default for older files */ - ob->linearStiffness = 1.0f; - ob->angularStiffness = 1.0f; - ob->volumePreservation = 1.0f; - ob->softflag = OB_SOFT_SHAPE_MATCHING; } } diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 2fed5e6170b..c12da6b0194 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -157,15 +157,8 @@ typedef struct Object { float formfactor; float rdamping, sizefac; float margin; - /* for game engine soft body */ - float linearStiffness; - float angularStiffness; - float volumePreservation; - int gamesoftFlag; int pad3; - - char dt, dtx; char totcol; /* copy of mesh or curve or meta */ char actcol; /* currently selected material in the user interface */ @@ -418,8 +411,6 @@ extern Object workob; #define OB_RECALC_TIME 4 #define OB_RECALC 7 -/* ob->gamesoftFlag */ -#define OB_SOFT_SHAPE_MATCHING 1 /* ob->gameflag */ #define OB_DYNAMIC 1 diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index dd374af8675..a6f4acb8c68 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -49,6 +49,7 @@ #include "DNA_controller_types.h" #include "DNA_property_types.h" #include "DNA_object_types.h" +#include "DNA_object_force.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_scene_types.h" @@ -2926,9 +2927,9 @@ void buttons_ketsji(uiBlock *block, Object *ob) uiBlockBeginAlign(block); uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 10, 105, 75, 19, &ob->gameflag, 0, 0,0, 0, - "Specify a bounds object for physics"); + "Specify a collision shape bounds type"); if (ob->gameflag & OB_BOUNDS) { - uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull%x5|Static TriangleMesh %x4", + uiDefButS(block, MENU, REDRAWVIEW3D, "Collision Type%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull%x5|Concave TriangleMesh %x4", 85, 105, 160, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 250,105,100,19, &ob->gameflag, 0, 0, 0, 0, @@ -3009,22 +3010,30 @@ static uiBlock *advanced_bullet_menu(void *arg_ob) "Collision margin"); } if (ob->gameflag & OB_SOFT_BODY) { - uiDefButBitI(block, TOG, OB_SOFT_SHAPE_MATCHING, 0, "Shape matching", - xco+=120, yco, 118, 19, &ob->gamesoftFlag, 0, 0, 0, 0, - "Enable soft body shape matching"); - yco -= 25; - xco = 0; - uiDefButF(block, NUMSLI, 0, "LinStiff ", xco, yco, 238, 19, - &ob->linearStiffness, 0.0, 1.0, 1, 0, - "Linear stiffness of the soft body vertex spring"); - yco -= 25; - uiDefButF(block, NUMSLI, 0, "AngStiff ", xco, yco, 238, 19, - &ob->angularStiffness, 0.0, 1.0, 1, 0, - "Angular stiffness of the soft body vertex spring"); - yco -= 25; - uiDefButF(block, NUMSLI, 0, "Volume ", xco, yco, 238, 19, - &ob->volumePreservation, 0.0, 1.0, 1, 0, - "Factor of soft body volume preservation"); + if (ob->soft) + { + + uiDefButBitI(block, TOG, OB_SB_GOAL, 0, "Shape matching", + xco+=120, yco, 118, 19, &ob->softflag, 0, 0, 0, 0, + "Enable soft body shape matching goal"); + yco -= 25; + xco = 0; + uiDefButF(block, NUMSLI, 0, "LinStiff ", xco, yco, 238, 19, + &ob->soft->inspring, 0.0, 1.0, 1, 0, + "Linear stiffness of the soft body vertex spring"); + /* + yco -= 25; + uiDefButF(block, NUMSLI, 0, "AngStiff ", xco, yco, 238, 19, + &ob->angularStiffness, 0.0, 1.0, 1, 0, + "Angular stiffness of the soft body vertex spring"); + yco -= 25; + uiDefButF(block, NUMSLI, 0, "Volume ", xco, yco, 238, 19, + &ob->volumePreservation, 0.0, 1.0, 1, 0, + "Factor of soft body volume preservation"); + */ + + } + } @@ -3049,10 +3058,21 @@ void buttons_bullet(uiBlock *block, Object *ob) else ob->body_type = OB_BODY_TYPE_SOFT; - but = uiDefButS(block, MENU, REDRAWVIEW3D, - "Object type%t|No collision%x0|Static%x1|Dynamic%x2|Rigid body%x3|Soft body%x4", - 10, 205, 120, 19, &ob->body_type, 0, 0, 0, 0, "Selects the type of physical representation"); - uiButSetFunc(but, check_body_type, but, ob); + //only enable game soft body if Blender Soft Body exists + if (ob->soft) + { + but = uiDefButS(block, MENU, REDRAWVIEW3D, + "Object type%t|No collision%x0|Static%x1|Dynamic%x2|Rigid body%x3|Soft body%x4", + 10, 205, 120, 19, &ob->body_type, 0, 0, 0, 0, "Selects the type of physical representation"); + uiButSetFunc(but, check_body_type, but, ob); + } else + { + but = uiDefButS(block, MENU, REDRAWVIEW3D, + "Object type%t|No collision%x0|Static%x1|Dynamic%x2|Rigid body%x3", + 10, 205, 120, 19, &ob->body_type, 0, 0, 0, 0, "Selects the type of physical representation"); + uiButSetFunc(but, check_body_type, but, ob); + } + if (ob->gameflag & OB_COLLISION) { @@ -3088,9 +3108,9 @@ void buttons_bullet(uiBlock *block, Object *ob) uiBlockBeginAlign(block); uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 10, 105, 80, 19, &ob->gameflag, 0, 0, 0, 0, - "Specify a bounds object for physics"); + "Specify a collision bounds type"); if (ob->gameflag & OB_BOUNDS) { - uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull%x5|Static Mesh%x4", + uiDefButS(block, MENU, REDRAWVIEW3D, "Collision Bounds%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull%x5|Triangle Mesh%x4", //almost ready to enable this one: uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull Polytope%x5|Static TriangleMesh %x4|Dynamic Mesh %x5|", 90, 105, 150, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 240,105,110,19, diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index 7cc8138cb6f..6f926f7396e 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -3529,10 +3529,10 @@ void copy_attr(short event) base->object->boundtype = ob->boundtype; } base->object->margin= ob->margin; - base->object->linearStiffness= ob->linearStiffness; - base->object->angularStiffness= ob->angularStiffness; - base->object->volumePreservation= ob->volumePreservation; - base->object->gamesoftFlag= ob->gamesoftFlag; + //base->object->linearStiffness= ob->linearStiffness; + //base->object->angularStiffness= ob->angularStiffness; + //base->object->volumePreservation= ob->volumePreservation; + //base->object->gamesoftFlag= ob->gamesoftFlag; } else if(event==17) { /* tex space */ copy_texture_space(base->object, ob); diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index b3df2d7bc85..5b72a10cd0d 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -129,6 +129,7 @@ #include "DNA_sound_types.h" #include "DNA_key_types.h" #include "DNA_armature_types.h" +#include "DNA_object_force.h" #include "MEM_guardedalloc.h" #include "BKE_utildefines.h" @@ -1323,10 +1324,20 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, objprop.m_angular_rigidbody = (blenderobject->gameflag & OB_RIGID_BODY) != 0; ///for game soft bodies - objprop.m_linearStiffness = blenderobject->linearStiffness; - objprop.m_angularStiffness = blenderobject->angularStiffness; - objprop.m_volumePreservation = blenderobject->volumePreservation; - objprop.m_gamesoftFlag = blenderobject->gamesoftFlag; + if (blenderobject->soft) + { + objprop.m_linearStiffness = blenderobject->soft->inspring; + objprop.m_angularStiffness = 1.f;//blenderobject->angularStiffness; + objprop.m_volumePreservation = 1.f;//blenderobject->volumePreservation; + objprop.m_gamesoftFlag = blenderobject->softflag;//blenderobject->gamesoftFlag; + + } else + { + objprop.m_linearStiffness = 0.5;//blenderobject->linearStiffness; + objprop.m_angularStiffness = 1.f;//blenderobject->angularStiffness; + objprop.m_volumePreservation = 1.f;//blenderobject->volumePreservation; + objprop.m_gamesoftFlag = 1;//blenderobject->gamesoftFlag; + } objprop.m_ghost = (blenderobject->gameflag & OB_GHOST) != 0; objprop.m_disableSleeping = (blenderobject->gameflag & OB_COLLISION_RESPONSE) != 0;//abuse the OB_COLLISION_RESPONSE flag diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 333ecd6ea11..b24ff42a495 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -346,7 +346,6 @@ void CcdPhysicsController::CreateRigidbody() - //pm->m_kAST = 0.01f; //pm->m_kVST = 0.001f; psb->generateBendingConstraints(2,pm); @@ -354,7 +353,7 @@ void CcdPhysicsController::CreateRigidbody() //psb->m_cfg.viterations = 4; //psb->m_cfg.diterations = 4; //psb->m_cfg.citerations = 4; - if (m_cci.m_gamesoftFlag & 1)///OB_SOFT_SHAPE_MATCHING) + if (m_cci.m_gamesoftFlag & 2)//OB_SB_GOAL) { psb->setPose(false,true);// } else @@ -390,7 +389,7 @@ void CcdPhysicsController::CreateRigidbody() //psb->m_materials[0]->m_kLST = 0.1+(i/(btScalar)(n-1))*0.9; psb->setTotalMass(m_cci.m_mass); - //psb->generateClusters(8);//(64); + psb->generateClusters(8);//(64); psb->setCollisionFlags(0); // m_object->setCollisionShape(rbci.m_collisionShape); btTransform startTrans; -- cgit v1.2.3 From 27098d3aa019a010f83f94ce935a6de63680ca2c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 25 Sep 2008 17:43:06 +0000 Subject: [#17679] BGE print statement when start and when finish from Dalai Felinto (dfelinto) would useually not encourage prints in these cases, except its often useful to know if an error happened since you last pressed Pkey and without this you end up needing to manually clear the terminal. --- source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 6a296a3e244..cc141249561 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -359,6 +359,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, ketsjiengine->SetAnimFrameRate( (((double) blscene->r.frs_sec) / blscene->r.frs_sec_base) ); // the mainloop + printf("\nBlender Game Engine Started\n\n"); while (!exitrequested) { // first check if we want to exit @@ -394,6 +395,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, mousedevice->ConvertBlenderEvent(event,val); } } + printf("\nBlender Game Engine Finished\n\n"); exitstring = ketsjiengine->GetExitString(); // when exiting the mainloop -- cgit v1.2.3 From 9c08e86b062fe2faa69894faccdc0e2ce2d8190d Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Thu, 25 Sep 2008 17:53:15 +0000 Subject: avoid crash and apply force for soft bodies. copy normals for soft body vertices, to get proper lighting --- .../Ketsji/KX_BulletPhysicsController.cpp | 25 +++++++++++------ .../gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp | 7 +++++ .../Physics/Bullet/CcdPhysicsController.cpp | 31 ++++++++++++++-------- 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp index 539eaec4a7b..d7bd1e9c7cd 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp @@ -14,6 +14,7 @@ #include "PHY_IPhysicsEnvironment.h" #include "CcdPhysicsEnvironment.h" +#include "BulletSoftBody/btSoftBody.h" KX_BulletPhysicsController::KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna) @@ -148,8 +149,12 @@ void KX_BulletPhysicsController::setScaling(const MT_Vector3& scaling) } MT_Scalar KX_BulletPhysicsController::GetMass() { - - MT_Scalar invmass = GetRigidBody()->getInvMass(); + if (GetSoftBody()) + return GetSoftBody()->getTotalMass(); + + MT_Scalar invmass = 0.f; + if (GetRigidBody()) + invmass = GetRigidBody()->getInvMass(); if (invmass) return 1.f/invmass; return 0.f; @@ -167,7 +172,7 @@ void KX_BulletPhysicsController::setRigidBody(bool rigid) void KX_BulletPhysicsController::SuspendDynamics(bool ghost) { btRigidBody *body = GetRigidBody(); - if (body->getActivationState() != DISABLE_SIMULATION) + if (body && body->getActivationState() != DISABLE_SIMULATION) { btBroadphaseProxy* handle = body->getBroadphaseHandle(); m_savedCollisionFlags = body->getCollisionFlags(); @@ -186,7 +191,7 @@ void KX_BulletPhysicsController::SuspendDynamics(bool ghost) void KX_BulletPhysicsController::RestoreDynamics() { btRigidBody *body = GetRigidBody(); - if (body->getActivationState() == DISABLE_SIMULATION) + if (body && body->getActivationState() == DISABLE_SIMULATION) { GetPhysicsEnvironment()->updateCcdPhysicsController(this, m_savedMass, @@ -241,18 +246,22 @@ SG_Controller* KX_BulletPhysicsController::GetReplica(class SG_Node* destnode) void KX_BulletPhysicsController::SetSumoTransform(bool nondynaonly) { - GetRigidBody()->activate(true); + if (GetRigidBody()) + GetRigidBody()->activate(true); if (!m_bDyna) { - GetRigidBody()->setCollisionFlags(GetRigidBody()->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + GetCollisionObject()->setCollisionFlags(GetRigidBody()->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } else { if (!nondynaonly) { btTransform worldTrans; - GetRigidBody()->getMotionState()->getWorldTransform(worldTrans); - GetRigidBody()->setCenterOfMassTransform(worldTrans); + if (GetRigidBody()) + { + GetRigidBody()->getMotionState()->getWorldTransform(worldTrans); + GetRigidBody()->setCenterOfMassTransform(worldTrans); + } /* scaling? diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 5744a860e92..f90df047ca0 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -727,6 +727,13 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, nodes[v.getSoftBodyIndex()].m_x.getY(), nodes[v.getSoftBodyIndex()].m_x.getZ()); v.SetXYZ(pt); + + MT_Vector3 normal ( + nodes[v.getSoftBodyIndex()].m_n.getX(), + nodes[v.getSoftBodyIndex()].m_n.getY(), + nodes[v.getSoftBodyIndex()].m_n.getZ()); + v.SetNormal(normal); + } } return true; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index b24ff42a495..f8dc81e0f3d 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -862,15 +862,20 @@ void CcdPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bo m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } - btRigidBody* body = GetRigidBody(); - if (body) { - btTransform xform = body->getCenterOfMassTransform(); + btTransform xform = m_object->getWorldTransform(); + if (local) { force = xform.getBasis()*force; } - body->applyCentralForce(force); + btRigidBody* body = GetRigidBody(); + if (body) + body->applyCentralForce(force); + btSoftBody* soft = GetSoftBody(); + if (soft) + soft->addForce(force); + } } } @@ -884,15 +889,16 @@ void CcdPhysicsController::SetAngularVelocity(float ang_velX,float ang_velY,flo { m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } - btRigidBody* body = GetRigidBody(); - if (body) { - btTransform xform = body->getCenterOfMassTransform(); + btTransform xform = m_object->getWorldTransform(); if (local) { angvel = xform.getBasis()*angvel; } - body->setAngularVelocity(angvel); + btRigidBody* body = GetRigidBody(); + if (body) + body->setAngularVelocity(angvel); + } } @@ -908,15 +914,17 @@ void CcdPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,floa { m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } - btRigidBody* body = GetRigidBody(); - if (body) + { btTransform xform = m_object->getWorldTransform(); if (local) { linVel = xform.getBasis()*linVel; } - body->setLinearVelocity(linVel); + btRigidBody* body = GetRigidBody(); + if (body) + body->setLinearVelocity(linVel); + } } } @@ -936,6 +944,7 @@ void CcdPhysicsController::applyImpulse(float attachX,float attachY,float attac btRigidBody* body = GetRigidBody(); if (body) body->applyImpulse(impulse,pos); + } } -- cgit v1.2.3 From 9a7c53782b63ea084782f9843150f74bcaa2cca3 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Thu, 25 Sep 2008 18:31:01 +0000 Subject: Fix for [#17677] Blender Crash when Baking Boids - A check for getting the "better" dm was missing from the boids code. I plan on converting the boids code into using the collision modifier one of these days but hopefully this quick fix will do for now. --- source/blender/blenkernel/intern/particle_system.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 0b5a2b71119..e4b8077cd4e 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2861,7 +2861,7 @@ int psys_intersect_dm(Object *ob, DerivedMesh *dm, float *vert_cos, float *co1, dm=mesh_get_derived_final(ob,0); if(dm==0) - mesh_get_derived_deform(ob,0); + dm=mesh_get_derived_deform(ob,0); psys_enable_all(ob); @@ -3319,7 +3319,9 @@ static int boid_see_mesh(ListBase *lb, Object *pob, ParticleSystem *psys, float else{ psys_disable_all(ob); - dm=mesh_get_derived_deform(ob,0); + dm=mesh_get_derived_final(ob,0); + if(dm==0) + dm=mesh_get_derived_deform(ob,0); psys_enable_all(ob); } -- cgit v1.2.3 From 6732718ef1b7f212e2368cf237c08d72f13d06ab Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Thu, 25 Sep 2008 21:04:41 +0000 Subject: don't apply vertex transformation for deformable game soft bodies. set a fake world transform for game soft bodies, based on center of the AABB, so visiblity and some game logic works. note: this world transform is not smooth. --- .../gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp | 14 ++++++++++--- .../Physics/Bullet/CcdPhysicsController.cpp | 24 ++++++++++++++++++---- source/gameengine/Rasterizer/RAS_Deformer.h | 4 ++++ .../gameengine/Rasterizer/RAS_MaterialBucket.cpp | 5 ++++- 4 files changed, 39 insertions(+), 8 deletions(-) diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index f90df047ca0..7e684e5d5b7 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -672,11 +672,11 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, { btSoftBody* m_softBody; class RAS_MeshObject* m_pMeshObject; - class BL_DeformableGameObject* m_gameobj; + class KX_GameObject* m_gameobj; public: - KX_SoftBodyDeformer(btSoftBody* softBody,RAS_MeshObject* pMeshObject,BL_DeformableGameObject* gameobj) + KX_SoftBodyDeformer(btSoftBody* softBody,RAS_MeshObject* pMeshObject,KX_GameObject* gameobj) : m_softBody(softBody), m_pMeshObject(pMeshObject), m_gameobj(gameobj) @@ -703,6 +703,8 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, // update the vertex in m_transverts Update(); + + // The vertex cache can only be updated for this deformer: // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object) // share the same mesh (=the same cache). As the rendering is done per polymaterial @@ -748,6 +750,12 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, //printf("getReplica\n"); return 0; } + + virtual bool SkipVertexTransform() + { + return true; + } + protected: //class RAS_MeshObject *m_pMesh; }; @@ -1089,7 +1097,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, if (softBody && gameobj->GetMesh(0))//only the first mesh, if any { //should be a mesh then, so add a soft body deformer - KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer(softBody, gameobj->GetMesh(0),(BL_DeformableGameObject*)gameobj); + KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer(softBody, gameobj->GetMesh(0),gameobj); gameobj->SetDeformer(softbodyDeformer); } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index f8dc81e0f3d..29ee0310c58 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -401,13 +401,17 @@ void CcdPhysicsController::CreateRigidbody() { startTrans = rbci.m_startWorldTransform; } - startTrans.setIdentity(); + //startTrans.setIdentity(); - m_object->setWorldTransform(startTrans); - m_object->setInterpolationWorldTransform(startTrans); - m_MotionState->setWorldPosition(0,0,0); + //m_object->setWorldTransform(startTrans); + //m_object->setInterpolationWorldTransform(startTrans); + m_MotionState->setWorldPosition(startTrans.getOrigin().getX(),startTrans.getOrigin().getY(),startTrans.getOrigin().getZ()); m_MotionState->setWorldOrientation(0,0,0,1); +// btVector3 wp = m_softBody->getWorldTransform().getOrigin(); +// MT_Point3 center(wp.getX(),wp.getY(),wp.getZ()); +// m_gameobj->NodeSetWorldPosition(center); + } else { @@ -502,10 +506,22 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time) { //sync non-static to motionstate, and static from motionstate (todo: add kinematic etc.) + btSoftBody* sb = GetSoftBody(); + if (sb) + { + btVector3 aabbMin,aabbMax; + sb->getAabb(aabbMin,aabbMax); + btVector3 worldPos = (aabbMax+aabbMin)*0.5f; + m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]); + m_MotionState->calculateWorldTransformations(); + return true; + } + btRigidBody* body = GetRigidBody(); if (body && !body->isStaticObject()) { + const btVector3& worldPos = body->getCenterOfMassPosition(); m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]); diff --git a/source/gameengine/Rasterizer/RAS_Deformer.h b/source/gameengine/Rasterizer/RAS_Deformer.h index 4e8484ab880..6665e1926cf 100644 --- a/source/gameengine/Rasterizer/RAS_Deformer.h +++ b/source/gameengine/Rasterizer/RAS_Deformer.h @@ -45,6 +45,10 @@ public: virtual bool Apply(class RAS_IPolyMaterial *polymat)=0; virtual bool Update(void)=0; virtual RAS_Deformer *GetReplica()=0; + virtual bool SkipVertexTransform() + { + return false; + } protected: class RAS_MeshObject *m_pMesh; }; diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index 2b129f51609..ad8d7ebd5b0 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -539,7 +539,10 @@ void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRa ms.m_mesh->SortPolygons(ms, cameratrans*MT_Transform(ms.m_OpenGLMatrix)); rendertools->PushMatrix(); - rendertools->applyTransform(rasty,ms.m_OpenGLMatrix,m_material->GetDrawingMode()); + if (!ms.m_pDeformer || !ms.m_pDeformer->SkipVertexTransform()) + { + rendertools->applyTransform(rasty,ms.m_OpenGLMatrix,m_material->GetDrawingMode()); + } if(rasty->QueryLists()) if(ms.m_DisplayList) -- cgit v1.2.3 From a1bef84ea859cf85487d4cac8664402dd86f4465 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Fri, 26 Sep 2008 02:27:59 +0000 Subject: Allow Bullet soft bodies to be created using a AddObject actuator. Added a fake world coordinate system to game soft bodies, although the vertices are already in world space. Added Bullet/Gimpact concave collision detection to Blender. If your build system isn't updated yet, please add extern/bullet2/src/BulletCollision/Gimpact/* This allows moving/dynamic concave triangle meshes (decomposing meshes into compound convex shapes, and using 'compound' shapes is still preferred) --- extern/bullet2/CMakeLists.txt | 1 + extern/bullet2/Makefile | 1 + .../src/BulletCollision/Gimpact/btBoxCollision.h | 651 ++++++++ .../src/BulletCollision/Gimpact/btClipPolygon.h | 186 +++ .../Gimpact/btContactProcessing.cpp | 181 +++ .../BulletCollision/Gimpact/btContactProcessing.h | 149 ++ .../src/BulletCollision/Gimpact/btGImpactBvh.cpp | 499 ++++++ .../src/BulletCollision/Gimpact/btGImpactBvh.h | 401 +++++ .../Gimpact/btGImpactCollisionAlgorithm.cpp | 896 +++++++++++ .../Gimpact/btGImpactCollisionAlgorithm.h | 306 ++++ .../BulletCollision/Gimpact/btGImpactMassUtil.h | 60 + .../Gimpact/btGImpactQuantizedBvh.cpp | 529 +++++++ .../Gimpact/btGImpactQuantizedBvh.h | 379 +++++ .../src/BulletCollision/Gimpact/btGImpactShape.cpp | 183 +++ .../src/BulletCollision/Gimpact/btGImpactShape.h | 1109 ++++++++++++++ .../Gimpact/btGenericPoolAllocator.cpp | 283 ++++ .../Gimpact/btGenericPoolAllocator.h | 168 +++ .../BulletCollision/Gimpact/btGeometryOperations.h | 216 +++ .../src/BulletCollision/Gimpact/btQuantization.h | 92 ++ .../BulletCollision/Gimpact/btTriangleShapeEx.cpp | 218 +++ .../BulletCollision/Gimpact/btTriangleShapeEx.h | 180 +++ .../src/BulletCollision/Gimpact/gim_array.h | 332 ++++ .../Gimpact/gim_basic_geometry_operations.h | 547 +++++++ .../src/BulletCollision/Gimpact/gim_bitset.h | 129 ++ .../BulletCollision/Gimpact/gim_box_collision.h | 594 ++++++++ .../src/BulletCollision/Gimpact/gim_box_set.cpp | 182 +++ .../src/BulletCollision/Gimpact/gim_box_set.h | 678 +++++++++ .../src/BulletCollision/Gimpact/gim_clip_polygon.h | 214 +++ .../src/BulletCollision/Gimpact/gim_contact.cpp | 146 ++ .../src/BulletCollision/Gimpact/gim_contact.h | 172 +++ .../src/BulletCollision/Gimpact/gim_geom_types.h | 102 ++ .../src/BulletCollision/Gimpact/gim_geometry.h | 42 + .../src/BulletCollision/Gimpact/gim_hash_table.h | 920 ++++++++++++ .../src/BulletCollision/Gimpact/gim_linear_math.h | 1584 ++++++++++++++++++++ .../bullet2/src/BulletCollision/Gimpact/gim_math.h | 181 +++ .../src/BulletCollision/Gimpact/gim_memory.cpp | 135 ++ .../src/BulletCollision/Gimpact/gim_memory.h | 211 +++ .../src/BulletCollision/Gimpact/gim_radixsort.h | 410 +++++ .../BulletCollision/Gimpact/gim_tri_collision.cpp | 640 ++++++++ .../BulletCollision/Gimpact/gim_tri_collision.h | 383 +++++ extern/bullet2/src/BulletSoftBody/btSoftBody.cpp | 14 + extern/bullet2/src/BulletSoftBody/btSoftBody.h | 4 + extern/bullet2/src/SConscript | 2 +- .../Converter/BL_DeformableGameObject.cpp | 2 +- source/gameengine/Converter/BL_MeshDeformer.h | 2 +- source/gameengine/Converter/BL_ShapeDeformer.cpp | 2 +- source/gameengine/Converter/BL_ShapeDeformer.h | 2 +- source/gameengine/Converter/BL_SkinDeformer.cpp | 2 +- source/gameengine/Converter/BL_SkinDeformer.h | 2 +- .../gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp | 35 +- .../Physics/Bullet/CcdPhysicsController.cpp | 97 +- .../Physics/Bullet/CcdPhysicsController.h | 13 +- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 5 +- source/gameengine/Rasterizer/RAS_Deformer.h | 2 +- source/gameengine/Rasterizer/RAS_TexVert.cpp | 1 + 55 files changed, 14429 insertions(+), 46 deletions(-) create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btBoxCollision.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btClipPolygon.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.cpp create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btGImpactBvh.cpp create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btGImpactBvh.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btGImpactMassUtil.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btGeometryOperations.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btQuantization.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.cpp create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_array.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_basic_geometry_operations.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_bitset.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_box_collision.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.cpp create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_clip_polygon.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_contact.cpp create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_contact.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_geom_types.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_geometry.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_hash_table.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_linear_math.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_math.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_memory.cpp create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_memory.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_radixsort.h create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_tri_collision.cpp create mode 100644 extern/bullet2/src/BulletCollision/Gimpact/gim_tri_collision.h diff --git a/extern/bullet2/CMakeLists.txt b/extern/bullet2/CMakeLists.txt index e28e811087f..edb6b9c525f 100644 --- a/extern/bullet2/CMakeLists.txt +++ b/extern/bullet2/CMakeLists.txt @@ -31,6 +31,7 @@ FILE(GLOB SRC src/BulletCollision/BroadphaseCollision/*.cpp src/BulletCollision/CollisionShapes/*.cpp src/BulletCollision/NarrowPhaseCollision/*.cpp + src/BulletCollision/Gimpact/*.cpp src/BulletCollision//CollisionDispatch/*.cpp src/BulletDynamics/ConstraintSolver/*.cpp src/BulletDynamics/Vehicle/*.cpp diff --git a/extern/bullet2/Makefile b/extern/bullet2/Makefile index d26289c8b01..f3abb86e404 100644 --- a/extern/bullet2/Makefile +++ b/extern/bullet2/Makefile @@ -37,6 +37,7 @@ LinearMath \ BulletCollision/BroadphaseCollision \ BulletCollision/CollisionShapes \ BulletCollision/NarrowPhaseCollision \ +BulletCollision/Gimpact \ BulletCollision//CollisionDispatch \ BulletDynamics/ConstraintSolver \ BulletDynamics/Vehicle \ diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btBoxCollision.h b/extern/bullet2/src/BulletCollision/Gimpact/btBoxCollision.h new file mode 100644 index 00000000000..c98526f09f8 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/btBoxCollision.h @@ -0,0 +1,651 @@ +#ifndef BT_BOX_COLLISION_H_INCLUDED +#define BT_BOX_COLLISION_H_INCLUDED + +/*! \file gim_box_collision.h +\author Francisco León Nájera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "LinearMath/btTransform.h" + +/*! \defgroup BOUND_AABB_OPERATIONS +*/ +//! @{ + +///Swap numbers +#define BT_SWAP_NUMBERS(a,b){ \ + a = a+b; \ + b = a-b; \ + a = a-b; \ +}\ + + +#define BT_MAX(a,b) (ab?b:a) + +#define BT_GREATER(x, y) fabsf(x) > (y) + +#define BT_MAX3(a,b,c) BT_MAX(a,BT_MAX(b,c)) +#define BT_MIN3(a,b,c) BT_MIN(a,BT_MIN(b,c)) + + + + + + +enum eBT_PLANE_INTERSECTION_TYPE +{ + BT_CONST_BACK_PLANE = 0, + BT_CONST_COLLIDE_PLANE, + BT_CONST_FRONT_PLANE +}; + +//SIMD_FORCE_INLINE bool test_cross_edge_box( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, const btVector3 & extend, +// int dir_index0, +// int dir_index1 +// int component_index0, +// int component_index1) +//{ +// // dir coords are -z and y +// +// const btScalar dir0 = -edge[dir_index0]; +// const btScalar dir1 = edge[dir_index1]; +// btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1; +// btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1; +// //find minmax +// if(pmin>pmax) +// { +// BT_SWAP_NUMBERS(pmin,pmax); +// } +// //find extends +// const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] + +// extend[component_index1] * absolute_edge[dir_index1]; +// +// if(pmin>rad || -rad>pmax) return false; +// return true; +//} +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2); +//} +// +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0); +//} +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1); +//} + + +#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\ +{\ + const btScalar dir0 = -edge[i_dir_0];\ + const btScalar dir1 = edge[i_dir_1];\ + btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\ + btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\ + if(pmin>pmax)\ + {\ + BT_SWAP_NUMBERS(pmin,pmax); \ + }\ + const btScalar abs_dir0 = absolute_edge[i_dir_0];\ + const btScalar abs_dir1 = absolute_edge[i_dir_1];\ + const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\ + if(pmin>rad || -rad>pmax) return false;\ +}\ + + +#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\ +}\ + +#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\ +}\ + +#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\ +}\ + + +//! Returns the dot product between a vec3f and the col of a matrix +SIMD_FORCE_INLINE btScalar bt_mat3_dot_col( +const btMatrix3x3 & mat, const btVector3 & vec3, int colindex) +{ + return vec3[0]*mat[0][colindex] + vec3[1]*mat[1][colindex] + vec3[2]*mat[2][colindex]; +} + + +//! Class for transforming a model1 to the space of model0 +ATTRIBUTE_ALIGNED16 (class) BT_BOX_BOX_TRANSFORM_CACHE +{ +public: + btVector3 m_T1to0;//!< Transforms translation of model1 to model 0 + btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal to R0' * R1 + btMatrix3x3 m_AR;//!< Absolute value of m_R1to0 + + SIMD_FORCE_INLINE void calc_absolute_matrix() + { +// static const btVector3 vepsi(1e-6f,1e-6f,1e-6f); +// m_AR[0] = vepsi + m_R1to0[0].absolute(); +// m_AR[1] = vepsi + m_R1to0[1].absolute(); +// m_AR[2] = vepsi + m_R1to0[2].absolute(); + + int i,j; + + for(i=0;i<3;i++) + { + for(j=0;j<3;j++ ) + { + m_AR[i][j] = 1e-6f + fabsf(m_R1to0[i][j]); + } + } + + } + + BT_BOX_BOX_TRANSFORM_CACHE() + { + } + + + + //! Calc the transformation relative 1 to 0. Inverts matrics by transposing + SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1) + { + + btTransform temp_trans = trans0.inverse(); + temp_trans = temp_trans * trans1; + + m_T1to0 = temp_trans.getOrigin(); + m_R1to0 = temp_trans.getBasis(); + + + calc_absolute_matrix(); + } + + //! Calcs the full invertion of the matrices. Useful for scaling matrices + SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1) + { + m_R1to0 = trans0.getBasis().inverse(); + m_T1to0 = m_R1to0 * (-trans0.getOrigin()); + + m_T1to0 += m_R1to0*trans1.getOrigin(); + m_R1to0 *= trans1.getBasis(); + + calc_absolute_matrix(); + } + + SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point) const + { + return btVector3(m_R1to0[0].dot(point) + m_T1to0.x(), + m_R1to0[1].dot(point) + m_T1to0.y(), + m_R1to0[2].dot(point) + m_T1to0.z()); + } +}; + + +#define BOX_PLANE_EPSILON 0.000001f + +//! Axis aligned box +ATTRIBUTE_ALIGNED16 (class) btAABB +{ +public: + btVector3 m_min; + btVector3 m_max; + + btAABB() + {} + + + btAABB(const btVector3 & V1, + const btVector3 & V2, + const btVector3 & V3) + { + m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]); + } + + btAABB(const btVector3 & V1, + const btVector3 & V2, + const btVector3 & V3, + btScalar margin) + { + m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]); + + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + btAABB(const btAABB &other): + m_min(other.m_min),m_max(other.m_max) + { + } + + btAABB(const btAABB &other,btScalar margin ): + m_min(other.m_min),m_max(other.m_max) + { + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + SIMD_FORCE_INLINE void invalidate() + { + m_min[0] = SIMD_INFINITY; + m_min[1] = SIMD_INFINITY; + m_min[2] = SIMD_INFINITY; + m_max[0] = -SIMD_INFINITY; + m_max[1] = -SIMD_INFINITY; + m_max[2] = -SIMD_INFINITY; + } + + SIMD_FORCE_INLINE void increment_margin(btScalar margin) + { + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + SIMD_FORCE_INLINE void copy_with_margin(const btAABB &other, btScalar margin) + { + m_min[0] = other.m_min[0] - margin; + m_min[1] = other.m_min[1] - margin; + m_min[2] = other.m_min[2] - margin; + + m_max[0] = other.m_max[0] + margin; + m_max[1] = other.m_max[1] + margin; + m_max[2] = other.m_max[2] + margin; + } + + template + SIMD_FORCE_INLINE void calc_from_triangle( + const CLASS_POINT & V1, + const CLASS_POINT & V2, + const CLASS_POINT & V3) + { + m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]); + } + + template + SIMD_FORCE_INLINE void calc_from_triangle_margin( + const CLASS_POINT & V1, + const CLASS_POINT & V2, + const CLASS_POINT & V3, btScalar margin) + { + m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]); + + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + //! Apply a transform to an AABB + SIMD_FORCE_INLINE void appy_transform(const btTransform & trans) + { + btVector3 center = (m_max+m_min)*0.5f; + btVector3 extends = m_max - center; + // Compute new center + center = trans(center); + + btVector3 textends(extends.dot(trans.getBasis().getRow(0).absolute()), + extends.dot(trans.getBasis().getRow(1).absolute()), + extends.dot(trans.getBasis().getRow(2).absolute())); + + m_min = center - textends; + m_max = center + textends; + } + + + //! Apply a transform to an AABB + SIMD_FORCE_INLINE void appy_transform_trans_cache(const BT_BOX_BOX_TRANSFORM_CACHE & trans) + { + btVector3 center = (m_max+m_min)*0.5f; + btVector3 extends = m_max - center; + // Compute new center + center = trans.transform(center); + + btVector3 textends(extends.dot(trans.m_R1to0.getRow(0).absolute()), + extends.dot(trans.m_R1to0.getRow(1).absolute()), + extends.dot(trans.m_R1to0.getRow(2).absolute())); + + m_min = center - textends; + m_max = center + textends; + } + + //! Merges a Box + SIMD_FORCE_INLINE void merge(const btAABB & box) + { + m_min[0] = BT_MIN(m_min[0],box.m_min[0]); + m_min[1] = BT_MIN(m_min[1],box.m_min[1]); + m_min[2] = BT_MIN(m_min[2],box.m_min[2]); + + m_max[0] = BT_MAX(m_max[0],box.m_max[0]); + m_max[1] = BT_MAX(m_max[1],box.m_max[1]); + m_max[2] = BT_MAX(m_max[2],box.m_max[2]); + } + + //! Merges a point + template + SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point) + { + m_min[0] = BT_MIN(m_min[0],point[0]); + m_min[1] = BT_MIN(m_min[1],point[1]); + m_min[2] = BT_MIN(m_min[2],point[2]); + + m_max[0] = BT_MAX(m_max[0],point[0]); + m_max[1] = BT_MAX(m_max[1],point[1]); + m_max[2] = BT_MAX(m_max[2],point[2]); + } + + //! Gets the extend and center + SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const + { + center = (m_max+m_min)*0.5f; + extend = m_max - center; + } + + //! Finds the intersecting box between this box and the other. + SIMD_FORCE_INLINE void find_intersection(const btAABB & other, btAABB & intersection) const + { + intersection.m_min[0] = BT_MAX(other.m_min[0],m_min[0]); + intersection.m_min[1] = BT_MAX(other.m_min[1],m_min[1]); + intersection.m_min[2] = BT_MAX(other.m_min[2],m_min[2]); + + intersection.m_max[0] = BT_MIN(other.m_max[0],m_max[0]); + intersection.m_max[1] = BT_MIN(other.m_max[1],m_max[1]); + intersection.m_max[2] = BT_MIN(other.m_max[2],m_max[2]); + } + + + SIMD_FORCE_INLINE bool has_collision(const btAABB & other) const + { + if(m_min[0] > other.m_max[0] || + m_max[0] < other.m_min[0] || + m_min[1] > other.m_max[1] || + m_max[1] < other.m_min[1] || + m_min[2] > other.m_max[2] || + m_max[2] < other.m_min[2]) + { + return false; + } + return true; + } + + /*! \brief Finds the Ray intersection parameter. + \param aabb Aligned box + \param vorigin A vec3f with the origin of the ray + \param vdir A vec3f with the direction of the ray + */ + SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir) const + { + btVector3 extents,center; + this->get_center_extend(center,extents);; + + btScalar Dx = vorigin[0] - center[0]; + if(BT_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false; + btScalar Dy = vorigin[1] - center[1]; + if(BT_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false; + btScalar Dz = vorigin[2] - center[2]; + if(BT_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false; + + + btScalar f = vdir[1] * Dz - vdir[2] * Dy; + if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false; + f = vdir[2] * Dx - vdir[0] * Dz; + if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false; + f = vdir[0] * Dy - vdir[1] * Dx; + if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false; + return true; + } + + + SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const + { + btVector3 center = (m_max+m_min)*0.5f; + btVector3 extend = m_max-center; + + btScalar _fOrigin = direction.dot(center); + btScalar _fMaximumExtent = extend.dot(direction.absolute()); + vmin = _fOrigin - _fMaximumExtent; + vmax = _fOrigin + _fMaximumExtent; + } + + SIMD_FORCE_INLINE eBT_PLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const + { + btScalar _fmin,_fmax; + this->projection_interval(plane,_fmin,_fmax); + + if(plane[3] > _fmax + BOX_PLANE_EPSILON) + { + return BT_CONST_BACK_PLANE; // 0 + } + + if(plane[3]+BOX_PLANE_EPSILON >=_fmin) + { + return BT_CONST_COLLIDE_PLANE; //1 + } + return BT_CONST_FRONT_PLANE;//2 + } + + SIMD_FORCE_INLINE bool overlapping_trans_conservative(const btAABB & box, btTransform & trans1_to_0) const + { + btAABB tbox = box; + tbox.appy_transform(trans1_to_0); + return has_collision(tbox); + } + + SIMD_FORCE_INLINE bool overlapping_trans_conservative2(const btAABB & box, + const BT_BOX_BOX_TRANSFORM_CACHE & trans1_to_0) const + { + btAABB tbox = box; + tbox.appy_transform_trans_cache(trans1_to_0); + return has_collision(tbox); + } + + //! transcache is the transformation cache from box to this AABB + SIMD_FORCE_INLINE bool overlapping_trans_cache( + const btAABB & box,const BT_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest) const + { + + //Taken from OPCODE + btVector3 ea,eb;//extends + btVector3 ca,cb;//extends + get_center_extend(ca,ea); + box.get_center_extend(cb,eb); + + + btVector3 T; + btScalar t,t2; + int i; + + // Class I : A's basis vectors + for(i=0;i<3;i++) + { + T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i]; + t = transcache.m_AR[i].dot(eb) + ea[i]; + if(BT_GREATER(T[i], t)) return false; + } + // Class II : B's basis vectors + for(i=0;i<3;i++) + { + t = bt_mat3_dot_col(transcache.m_R1to0,T,i); + t2 = bt_mat3_dot_col(transcache.m_AR,ea,i) + eb[i]; + if(BT_GREATER(t,t2)) return false; + } + // Class III : 9 cross products + if(fulltest) + { + int j,m,n,o,p,q,r; + for(i=0;i<3;i++) + { + m = (i+1)%3; + n = (i+2)%3; + o = i==0?1:0; + p = i==2?1:2; + for(j=0;j<3;j++) + { + q = j==2?1:2; + r = j==0?1:0; + t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j]; + t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] + + eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r]; + if(BT_GREATER(t,t2)) return false; + } + } + } + return true; + } + + //! Simple test for planes. + SIMD_FORCE_INLINE bool collide_plane( + const btVector4 & plane) const + { + eBT_PLANE_INTERSECTION_TYPE classify = plane_classify(plane); + return (classify == BT_CONST_COLLIDE_PLANE); + } + + //! test for a triangle, with edges + SIMD_FORCE_INLINE bool collide_triangle_exact( + const btVector3 & p1, + const btVector3 & p2, + const btVector3 & p3, + const btVector4 & triangle_plane) const + { + if(!collide_plane(triangle_plane)) return false; + + btVector3 center,extends; + this->get_center_extend(center,extends); + + const btVector3 v1(p1 - center); + const btVector3 v2(p2 - center); + const btVector3 v3(p3 - center); + + //First axis + btVector3 diff(v2 - v1); + btVector3 abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends); + + + diff = v3 - v2; + abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends); + + diff = v1 - v3; + abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends); + + return true; + } +}; + + +//! Compairison of transformation objects +SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2) +{ + if(!(t1.getOrigin() == t2.getOrigin()) ) return false; + + if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false; + if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false; + if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false; + return true; +} + + +//! @} + +#endif // GIM_BOX_COLLISION_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btClipPolygon.h b/extern/bullet2/src/BulletCollision/Gimpact/btClipPolygon.h new file mode 100644 index 00000000000..32d470a2398 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/btClipPolygon.h @@ -0,0 +1,186 @@ +#ifndef BT_CLIP_POLYGON_H_INCLUDED +#define BT_CLIP_POLYGON_H_INCLUDED + +/*! \file btClipPolygon.h +\author Francisco León Nájera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "LinearMath/btTransform.h" +#include "LinearMath/btGeometryUtil.h" + +/*! \addtogroup GEOMETRIC_OPERATIONS +*/ +//! @{ + +SIMD_FORCE_INLINE btScalar bt_distance_point_plane(const btVector4 & plane,const btVector3 &point) +{ + return point.dot(plane) - plane[3]; +} + +/*! Vector blending +Takes two vectors a, b, blends them together*/ +SIMD_FORCE_INLINE void bt_vec_blend(btVector3 &vr, const btVector3 &va,const btVector3 &vb, btScalar blend_factor) +{ + vr = (1-blend_factor)*va + blend_factor*vb; +} + +//! This function calcs the distance from a 3D plane +SIMD_FORCE_INLINE void bt_plane_clip_polygon_collect( + const btVector3 & point0, + const btVector3 & point1, + btScalar dist0, + btScalar dist1, + btVector3 * clipped, + int & clipped_count) +{ + bool _prevclassif = (dist0>SIMD_EPSILON); + bool _classif = (dist1>SIMD_EPSILON); + if(_classif!=_prevclassif) + { + btScalar blendfactor = -dist0/(dist1-dist0); + bt_vec_blend(clipped[clipped_count],point0,point1,blendfactor); + clipped_count++; + } + if(!_classif) + { + clipped[clipped_count] = point1; + clipped_count++; + } +} + + +//! Clips a polygon by a plane +/*! +*\return The count of the clipped counts +*/ +SIMD_FORCE_INLINE int bt_plane_clip_polygon( + const btVector4 & plane, + const btVector3 * polygon_points, + int polygon_point_count, + btVector3 * clipped) +{ + int clipped_count = 0; + + + //clip first point + btScalar firstdist = bt_distance_point_plane(plane,polygon_points[0]);; + if(!(firstdist>SIMD_EPSILON)) + { + clipped[clipped_count] = polygon_points[0]; + clipped_count++; + } + + btScalar olddist = firstdist; + for(int i=1;iSIMD_EPSILON)) + { + clipped[clipped_count] = point0; + clipped_count++; + } + + // point 1 + btScalar olddist = firstdist; + btScalar dist = bt_distance_point_plane(plane,point1); + + bt_plane_clip_polygon_collect( + point0,point1, + olddist, + dist, + clipped, + clipped_count); + + olddist = dist; + + + // point 2 + dist = bt_distance_point_plane(plane,point2); + + bt_plane_clip_polygon_collect( + point1,point2, + olddist, + dist, + clipped, + clipped_count); + olddist = dist; + + + + //RETURN TO FIRST point0 + bt_plane_clip_polygon_collect( + point2,point0, + olddist, + firstdist, + clipped, + clipped_count); + + return clipped_count; +} + + + + +//! @} + +#endif // GIM_TRI_COLLISION_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.cpp new file mode 100644 index 00000000000..faba2d8a542 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/btContactProcessing.cpp @@ -0,0 +1,181 @@ + +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +#include "btContactProcessing.h" + +#define MAX_COINCIDENT 8 + +struct CONTACT_KEY_TOKEN +{ + unsigned int m_key; + int m_value; + CONTACT_KEY_TOKEN() + { + } + + CONTACT_KEY_TOKEN(unsigned int key,int token) + { + m_key = key; + m_value = token; + } + + CONTACT_KEY_TOKEN(const CONTACT_KEY_TOKEN& rtoken) + { + m_key = rtoken.m_key; + m_value = rtoken.m_value; + } + + inline bool operator <(const CONTACT_KEY_TOKEN& other) const + { + return (m_key < other.m_key); + } + + inline bool operator >(const CONTACT_KEY_TOKEN& other) const + { + return (m_key > other.m_key); + } + +}; + +class CONTACT_KEY_TOKEN_COMP +{ + public: + + bool operator() ( const CONTACT_KEY_TOKEN& a, const CONTACT_KEY_TOKEN& b ) + { + return ( a < b ); + } +}; + + +void btContactArray::merge_contacts( + const btContactArray & contacts, bool normal_contact_average) +{ + clear(); + + int i; + if(contacts.size()==0) return; + + + if(contacts.size()==1) + { + push_back(contacts[0]); + return; + } + + btAlignedObjectArray keycontacts; + + keycontacts.reserve(contacts.size()); + + //fill key contacts + + for ( i = 0;im_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//) + { + *pcontact = *scontact; + coincident_count = 0; + } + else if(normal_contact_average) + { + if(btFabs(pcontact->m_depth - scontact->m_depth)m_normal; + coincident_count++; + } + } + } + } + else + {//add new contact + + if(normal_contact_average && coincident_count>0) + { + pcontact->interpolate_normals(coincident_normals,coincident_count); + coincident_count = 0; + } + + push_back(*scontact); + pcontact = &(*this)[this->size()-1]; + } + last_key = key; + } +} + +void btContactArray::merge_contacts_unique(const btContactArray & contacts) +{ + clear(); + + if(contacts.size()==0) return; + + if(contacts.size()==1) + { + push_back(contacts[0]); + return; + } + + BT_CONTACT average_contact = contacts[0]; + + for (int i=1;i +{ +public: + btContactArray() + { + reserve(64); + } + + SIMD_FORCE_INLINE void push_contact( + const btVector3 &point,const btVector3 & normal, + btScalar depth, int feature1, int feature2) + { + push_back( BT_CONTACT(point,normal,depth,feature1,feature2) ); + } + + SIMD_FORCE_INLINE void push_triangle_contacts( + const BT_TRIANGLE_CONTACT & tricontact, + int feature1,int feature2) + { + for(int i = 0;i splitValue) + { + //swap + primitive_boxes.swap(i,splitIndex); + //swapLeafNodes(i,splitIndex); + splitIndex++; + } + } + + //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex + //otherwise the tree-building might fail due to stack-overflows in certain cases. + //unbalanced1 is unsafe: it can cause stack overflows + //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); + + //unbalanced2 should work too: always use center (perfect balanced trees) + //bool unbalanced2 = true; + + //this should be safe too: + int rangeBalancedIndices = numIndices/3; + bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); + + if (unbalanced) + { + splitIndex = startIndex+ (numIndices>>1); + } + + bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); + btAssert(!unbal); + + return splitIndex; + +} + + +void btBvhTree::_build_sub_tree(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex) +{ + int curIndex = m_num_nodes; + m_num_nodes++; + + btAssert((endIndex-startIndex)>0); + + if ((endIndex-startIndex)==1) + { + //We have a leaf node + setNodeBound(curIndex,primitive_boxes[startIndex].m_bound); + m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data); + + return; + } + //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. + + //split axis + int splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex); + + splitIndex = _sort_and_calc_splitting_index( + primitive_boxes,startIndex,endIndex, + splitIndex//split axis + ); + + + //calc this node bounding box + + btAABB node_bound; + node_bound.invalidate(); + + for (int i=startIndex;iget_primitive_box(getNodeData(nodecount),leafbox); + setNodeBound(nodecount,leafbox); + } + else + { + //const BT_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount); + //get left bound + btAABB bound; + bound.invalidate(); + + btAABB temp_box; + + int child_node = getLeftNode(nodecount); + if(child_node) + { + getNodeBound(child_node,temp_box); + bound.merge(temp_box); + } + + child_node = getRightNode(nodecount); + if(child_node) + { + getNodeBound(child_node,temp_box); + bound.merge(temp_box); + } + + setNodeBound(nodecount,bound); + } + } +} + +//! this rebuild the entire set +void btGImpactBvh::buildSet() +{ + //obtain primitive boxes + BT_BVH_DATA_ARRAY primitive_boxes; + primitive_boxes.resize(m_primitive_manager->get_primitive_count()); + + for (int i = 0;iget_primitive_box(i,primitive_boxes[i].m_bound); + primitive_boxes[i].m_data = i; + } + + m_box_tree.build_tree(primitive_boxes); +} + +//! returns the indices of the primitives in the m_primitive_manager +bool btGImpactBvh::boxQuery(const btAABB & box, btAlignedObjectArray & collided_results) const +{ + int curIndex = 0; + int numNodes = getNodeCount(); + + while (curIndex < numNodes) + { + btAABB bound; + getNodeBound(curIndex,bound); + + //catch bugs in tree data + + bool aabbOverlap = bound.has_collision(box); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData(curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getEscapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; +} + + + +//! returns the indices of the primitives in the m_primitive_manager +bool btGImpactBvh::rayQuery( + const btVector3 & ray_dir,const btVector3 & ray_origin , + btAlignedObjectArray & collided_results) const +{ + int curIndex = 0; + int numNodes = getNodeCount(); + + while (curIndex < numNodes) + { + btAABB bound; + getNodeBound(curIndex,bound); + + //catch bugs in tree data + + bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData( curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getEscapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; +} + + +SIMD_FORCE_INLINE bool _node_collision( + btGImpactBvh * boxset0, btGImpactBvh * boxset1, + const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0, + int node0 ,int node1, bool complete_primitive_tests) +{ + btAABB box0; + boxset0->getNodeBound(node0,box0); + btAABB box1; + boxset1->getNodeBound(node1,box1); + + return box0.overlapping_trans_cache(box1,trans_cache_1to0,complete_primitive_tests ); +// box1.appy_transform_trans_cache(trans_cache_1to0); +// return box0.has_collision(box1); + +} + + +//stackless recursive collision routine +static void _find_collision_pairs_recursive( + btGImpactBvh * boxset0, btGImpactBvh * boxset1, + btPairSet * collision_pairs, + const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0, + int node0, int node1, bool complete_primitive_tests) +{ + + + + if( _node_collision( + boxset0,boxset1,trans_cache_1to0, + node0,node1,complete_primitive_tests) ==false) return;//avoid colliding internal nodes + + if(boxset0->isLeafNode(node0)) + { + if(boxset1->isLeafNode(node1)) + { + // collision result + collision_pairs->push_pair( + boxset0->getNodeData(node0),boxset1->getNodeData(node1)); + return; + } + else + { + + //collide left recursive + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + node0,boxset1->getLeftNode(node1),false); + + //collide right recursive + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + node0,boxset1->getRightNode(node1),false); + + + } + } + else + { + if(boxset1->isLeafNode(node1)) + { + + //collide left recursive + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),node1,false); + + + //collide right recursive + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),node1,false); + + + } + else + { + //collide left0 left1 + + + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),boxset1->getLeftNode(node1),false); + + //collide left0 right1 + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),boxset1->getRightNode(node1),false); + + + //collide right0 left1 + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),boxset1->getLeftNode(node1),false); + + //collide right0 right1 + + _find_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),boxset1->getRightNode(node1),false); + + }// else if node1 is not a leaf + }// else if node0 is not a leaf +} + + +void btGImpactBvh::find_collision(btGImpactBvh * boxset0, const btTransform & trans0, + btGImpactBvh * boxset1, const btTransform & trans1, + btPairSet & collision_pairs) +{ + + if(boxset0->getNodeCount()==0 || boxset1->getNodeCount()==0 ) return; + + BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0; + + trans_cache_1to0.calc_from_homogenic(trans0,trans1); + +#ifdef TRI_COLLISION_PROFILING + bt_begin_gim02_tree_time(); +#endif //TRI_COLLISION_PROFILING + + _find_collision_pairs_recursive( + boxset0,boxset1, + &collision_pairs,trans_cache_1to0,0,0,true); +#ifdef TRI_COLLISION_PROFILING + bt_end_gim02_tree_time(); +#endif //TRI_COLLISION_PROFILING + +} + diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactBvh.h b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactBvh.h new file mode 100644 index 00000000000..7138b2366aa --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactBvh.h @@ -0,0 +1,401 @@ +#ifndef GIM_BOX_SET_H_INCLUDED +#define GIM_BOX_SET_H_INCLUDED + +/*! \file gim_box_set.h +\author Francisco León Nájera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "LinearMath/btAlignedObjectArray.h" + +#include "btBoxCollision.h" +#include "btTriangleShapeEx.h" + + + +/*! \defgroup BOX_TREES + + + +*/ +//! @{ + + +//! Overlapping pair +struct BT_PAIR +{ + int m_index1; + int m_index2; + BT_PAIR() + {} + + BT_PAIR(const BT_PAIR & p) + { + m_index1 = p.m_index1; + m_index2 = p.m_index2; + } + + BT_PAIR(int index1, int index2) + { + m_index1 = index1; + m_index2 = index2; + } +}; + +//! A pairset array +class btPairSet: public btAlignedObjectArray +{ +public: + btPairSet() + { + reserve(32); + } + inline void push_pair(int index1,int index2) + { + push_back(BT_PAIR(index1,index2)); + } + + inline void push_pair_inv(int index1,int index2) + { + push_back(BT_PAIR(index2,index1)); + } +}; + + + +struct BT_BVH_DATA +{ + btAABB m_bound; + int m_data; +}; + +//! Node Structure for trees +class BT_BVH_TREE_NODE +{ +public: + btAABB m_bound; +protected: + int m_escapeIndexOrDataIndex; +public: + BT_BVH_TREE_NODE() + { + m_escapeIndexOrDataIndex = 0; + } + + SIMD_FORCE_INLINE bool isLeafNode() const + { + //skipindex is negative (internal node), triangleindex >=0 (leafnode) + return (m_escapeIndexOrDataIndex>=0); + } + + SIMD_FORCE_INLINE int getEscapeIndex() const + { + //btAssert(m_escapeIndexOrDataIndex < 0); + return -m_escapeIndexOrDataIndex; + } + + SIMD_FORCE_INLINE void setEscapeIndex(int index) + { + m_escapeIndexOrDataIndex = -index; + } + + SIMD_FORCE_INLINE int getDataIndex() const + { + //btAssert(m_escapeIndexOrDataIndex >= 0); + + return m_escapeIndexOrDataIndex; + } + + SIMD_FORCE_INLINE void setDataIndex(int index) + { + m_escapeIndexOrDataIndex = index; + } + +}; + + +class BT_BVH_DATA_ARRAY:public btAlignedObjectArray +{ +}; + + +class BT_BVH_TREE_NODE_ARRAY:public btAlignedObjectArray +{ +}; + + + + +//! Basic Box tree structure +class btBvhTree +{ +protected: + int m_num_nodes; + BT_BVH_TREE_NODE_ARRAY m_node_array; +protected: + int _sort_and_calc_splitting_index( + BT_BVH_DATA_ARRAY & primitive_boxes, + int startIndex, int endIndex, int splitAxis); + + int _calc_splitting_axis(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); + + void _build_sub_tree(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); +public: + btBvhTree() + { + m_num_nodes = 0; + } + + //! prototype functions for box tree management + //!@{ + void build_tree(BT_BVH_DATA_ARRAY & primitive_boxes); + + SIMD_FORCE_INLINE void clearNodes() + { + m_node_array.clear(); + m_num_nodes = 0; + } + + //! node count + SIMD_FORCE_INLINE int getNodeCount() const + { + return m_num_nodes; + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const + { + return m_node_array[nodeindex].isLeafNode(); + } + + SIMD_FORCE_INLINE int getNodeData(int nodeindex) const + { + return m_node_array[nodeindex].getDataIndex(); + } + + SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const + { + bound = m_node_array[nodeindex].m_bound; + } + + SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound) + { + m_node_array[nodeindex].m_bound = bound; + } + + SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const + { + return nodeindex+1; + } + + SIMD_FORCE_INLINE int getRightNode(int nodeindex) const + { + if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2; + return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex(); + } + + SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const + { + return m_node_array[nodeindex].getEscapeIndex(); + } + + SIMD_FORCE_INLINE const BT_BVH_TREE_NODE * get_node_pointer(int index = 0) const + { + return &m_node_array[index]; + } + + //!@} +}; + + +//! Prototype Base class for primitive classification +/*! +This class is a wrapper for primitive collections. +This tells relevant info for the Bounding Box set classes, which take care of space classification. +This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons. +*/ +class btPrimitiveManagerBase +{ +public: + + //! determines if this manager consist on only triangles, which special case will be optimized + virtual bool is_trimesh() const = 0; + virtual int get_primitive_count() const = 0; + virtual void get_primitive_box(int prim_index ,btAABB & primbox) const = 0; + //! retrieves only the points of the triangle, and the collision margin + virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const= 0; +}; + + +//! Structure for containing Boxes +/*! +This class offers an structure for managing a box tree of primitives. +Requires a Primitive prototype (like btPrimitiveManagerBase ) +*/ +class btGImpactBvh +{ +protected: + btBvhTree m_box_tree; + btPrimitiveManagerBase * m_primitive_manager; + +protected: + //stackless refit + void refit(); +public: + + //! this constructor doesn't build the tree. you must call buildSet + btGImpactBvh() + { + m_primitive_manager = NULL; + } + + //! this constructor doesn't build the tree. you must call buildSet + btGImpactBvh(btPrimitiveManagerBase * primitive_manager) + { + m_primitive_manager = primitive_manager; + } + + SIMD_FORCE_INLINE btAABB getGlobalBox() const + { + btAABB totalbox; + getNodeBound(0, totalbox); + return totalbox; + } + + SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager) + { + m_primitive_manager = primitive_manager; + } + + SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const + { + return m_primitive_manager; + } + + +//! node manager prototype functions +///@{ + + //! this attemps to refit the box set. + SIMD_FORCE_INLINE void update() + { + refit(); + } + + //! this rebuild the entire set + void buildSet(); + + //! returns the indices of the primitives in the m_primitive_manager + bool boxQuery(const btAABB & box, btAlignedObjectArray & collided_results) const; + + //! returns the indices of the primitives in the m_primitive_manager + SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box, + const btTransform & transform, btAlignedObjectArray & collided_results) const + { + btAABB transbox=box; + transbox.appy_transform(transform); + return boxQuery(transbox,collided_results); + } + + //! returns the indices of the primitives in the m_primitive_manager + bool rayQuery( + const btVector3 & ray_dir,const btVector3 & ray_origin , + btAlignedObjectArray & collided_results) const; + + //! tells if this set has hierarcht + SIMD_FORCE_INLINE bool hasHierarchy() const + { + return true; + } + + //! tells if this set is a trimesh + SIMD_FORCE_INLINE bool isTrimesh() const + { + return m_primitive_manager->is_trimesh(); + } + + //! node count + SIMD_FORCE_INLINE int getNodeCount() const + { + return m_box_tree.getNodeCount(); + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const + { + return m_box_tree.isLeafNode(nodeindex); + } + + SIMD_FORCE_INLINE int getNodeData(int nodeindex) const + { + return m_box_tree.getNodeData(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const + { + m_box_tree.getNodeBound(nodeindex, bound); + } + + SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound) + { + m_box_tree.setNodeBound(nodeindex, bound); + } + + + SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const + { + return m_box_tree.getLeftNode(nodeindex); + } + + SIMD_FORCE_INLINE int getRightNode(int nodeindex) const + { + return m_box_tree.getRightNode(nodeindex); + } + + SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const + { + return m_box_tree.getEscapeNodeIndex(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const + { + m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle); + } + + + SIMD_FORCE_INLINE const BT_BVH_TREE_NODE * get_node_pointer(int index = 0) const + { + return m_box_tree.get_node_pointer(index); + } + +//! @} + + static float getAverageTreeCollisionTime(); + + + static void find_collision(btGImpactBvh * boxset1, const btTransform & trans1, + btGImpactBvh * boxset2, const btTransform & trans2, + btPairSet & collision_pairs); +}; + + +#endif // GIM_BOXPRUNING_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp new file mode 100644 index 00000000000..60bcfe797b6 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.cpp @@ -0,0 +1,896 @@ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ +/* +Author: Francisco León Nájera +Concave-Concave Collision + +*/ + +#include "BulletCollision/CollisionDispatch/btManifoldResult.h" +#include "LinearMath/btIDebugDraw.h" +#include "BulletCollision/CollisionDispatch/btCollisionObject.h" +#include "BulletCollision/CollisionShapes/btBoxShape.h" +#include "btGImpactCollisionAlgorithm.h" +#include "btContactProcessing.h" +#include "LinearMath/btQuickprof.h" + + +//! Class for accessing the plane equation +class btPlaneShape : public btStaticPlaneShape +{ +public: + + btPlaneShape(const btVector3& v, float f) + :btStaticPlaneShape(v,f) + { + } + + void get_plane_equation(btVector4 &equation) + { + equation[0] = m_planeNormal[0]; + equation[1] = m_planeNormal[1]; + equation[2] = m_planeNormal[2]; + equation[3] = m_planeConstant; + } + + + void get_plane_equation_transformed(const btTransform & trans,btVector4 &equation) + { + equation[0] = trans.getBasis().getRow(0).dot(m_planeNormal); + equation[1] = trans.getBasis().getRow(1).dot(m_planeNormal); + equation[2] = trans.getBasis().getRow(2).dot(m_planeNormal); + equation[3] = trans.getOrigin().dot(m_planeNormal) + m_planeConstant; + } +}; + + + +////////////////////////////////////////////////////////////////////////////////////////////// +#ifdef TRI_COLLISION_PROFILING + +btClock g_triangle_clock; + +float g_accum_triangle_collision_time = 0; +int g_count_triangle_collision = 0; + +void bt_begin_gim02_tri_time() +{ + g_triangle_clock.reset(); +} + +void bt_end_gim02_tri_time() +{ + g_accum_triangle_collision_time += g_triangle_clock.getTimeMicroseconds(); + g_count_triangle_collision++; +} +#endif //TRI_COLLISION_PROFILING +//! Retrieving shapes shapes +/*! +Declared here due of insuficent space on Pool allocators +*/ +//!@{ +class GIM_ShapeRetriever +{ +public: + btGImpactShapeInterface * m_gim_shape; + btTriangleShapeEx m_trishape; + btTetrahedronShapeEx m_tetrashape; + +public: + class ChildShapeRetriever + { + public: + GIM_ShapeRetriever * m_parent; + virtual btCollisionShape * getChildShape(int index) + { + return m_parent->m_gim_shape->getChildShape(index); + } + }; + + class TriangleShapeRetriever:public ChildShapeRetriever + { + public: + + virtual btCollisionShape * getChildShape(int index) + { + m_parent->m_gim_shape->getBulletTriangle(index,m_parent->m_trishape); + return &m_parent->m_trishape; + } + }; + + class TetraShapeRetriever:public ChildShapeRetriever + { + public: + + virtual btCollisionShape * getChildShape(int index) + { + m_parent->m_gim_shape->getBulletTetrahedron(index,m_parent->m_tetrashape); + return &m_parent->m_tetrashape; + } + }; +public: + ChildShapeRetriever m_child_retriever; + TriangleShapeRetriever m_tri_retriever; + TetraShapeRetriever m_tetra_retriever; + ChildShapeRetriever * m_current_retriever; + + GIM_ShapeRetriever(btGImpactShapeInterface * gim_shape) + { + m_gim_shape = gim_shape; + //select retriever + if(m_gim_shape->needsRetrieveTriangles()) + { + m_current_retriever = &m_tri_retriever; + } + else if(m_gim_shape->needsRetrieveTetrahedrons()) + { + m_current_retriever = &m_tetra_retriever; + } + else + { + m_current_retriever = &m_child_retriever; + } + + m_current_retriever->m_parent = this; + } + + btCollisionShape * getChildShape(int index) + { + return m_current_retriever->getChildShape(index); + } + + +}; + + + +//!@} + + +#ifdef TRI_COLLISION_PROFILING + +//! Gets the average time in miliseconds of tree collisions +float btGImpactCollisionAlgorithm::getAverageTreeCollisionTime() +{ + return btGImpactBoxSet::getAverageTreeCollisionTime(); + +} + +//! Gets the average time in miliseconds of triangle collisions +float btGImpactCollisionAlgorithm::getAverageTriangleCollisionTime() +{ + if(g_count_triangle_collision == 0) return 0; + + float avgtime = g_accum_triangle_collision_time; + avgtime /= (float)g_count_triangle_collision; + + g_accum_triangle_collision_time = 0; + g_count_triangle_collision = 0; + + return avgtime; +} + +#endif //TRI_COLLISION_PROFILING + + + +btGImpactCollisionAlgorithm::btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) +: btCollisionAlgorithm(ci) +{ + m_manifoldPtr = NULL; + m_convex_algorithm = NULL; +} + +btGImpactCollisionAlgorithm::~btGImpactCollisionAlgorithm() +{ + clearCache(); +} + + + + + +void btGImpactCollisionAlgorithm::addContactPoint(btCollisionObject * body0, + btCollisionObject * body1, + const btVector3 & point, + const btVector3 & normal, + btScalar distance) +{ + m_resultOut->setShapeIdentifiers(m_part0,m_triface0,m_part1,m_triface1); + checkManifold(body0,body1); + m_resultOut->addContactPoint(normal,point,distance); +} + + +void btGImpactCollisionAlgorithm::shape_vs_shape_collision( + btCollisionObject * body0, + btCollisionObject * body1, + btCollisionShape * shape0, + btCollisionShape * shape1) +{ + + btCollisionShape* tmpShape0 = body0->getCollisionShape(); + btCollisionShape* tmpShape1 = body1->getCollisionShape(); + + body0->internalSetTemporaryCollisionShape(shape0); + body1->internalSetTemporaryCollisionShape(shape1); + + { + btCollisionAlgorithm* algor = newAlgorithm(body0,body1); + // post : checkManifold is called + + m_resultOut->setShapeIdentifiers(m_part0,m_triface0,m_part1,m_triface1); + + algor->processCollision(body0,body1,*m_dispatchInfo,m_resultOut); + + algor->~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm(algor); + } + + body0->internalSetTemporaryCollisionShape(tmpShape0); + body1->internalSetTemporaryCollisionShape(tmpShape1); +} + +void btGImpactCollisionAlgorithm::convex_vs_convex_collision( + btCollisionObject * body0, + btCollisionObject * body1, + btCollisionShape * shape0, + btCollisionShape * shape1) +{ + + btCollisionShape* tmpShape0 = body0->getCollisionShape(); + btCollisionShape* tmpShape1 = body1->getCollisionShape(); + + body0->internalSetTemporaryCollisionShape(shape0); + body1->internalSetTemporaryCollisionShape(shape1); + + + m_resultOut->setShapeIdentifiers(m_part0,m_triface0,m_part1,m_triface1); + + checkConvexAlgorithm(body0,body1); + m_convex_algorithm->processCollision(body0,body1,*m_dispatchInfo,m_resultOut); + + body0->internalSetTemporaryCollisionShape(tmpShape0); + body1->internalSetTemporaryCollisionShape(tmpShape1); + +} + + + + +void btGImpactCollisionAlgorithm::gimpact_vs_gimpact_find_pairs( + const btTransform & trans0, + const btTransform & trans1, + btGImpactShapeInterface * shape0, + btGImpactShapeInterface * shape1,btPairSet & pairset) +{ + if(shape0->hasBoxSet() && shape1->hasBoxSet()) + { + btGImpactBoxSet::find_collision(shape0->getBoxSet(),trans0,shape1->getBoxSet(),trans1,pairset); + } + else + { + btAABB boxshape0; + btAABB boxshape1; + int i = shape0->getNumChildShapes(); + + while(i--) + { + shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max); + + int j = shape1->getNumChildShapes(); + while(j--) + { + shape1->getChildAabb(i,trans1,boxshape1.m_min,boxshape1.m_max); + + if(boxshape1.has_collision(boxshape0)) + { + pairset.push_pair(i,j); + } + } + } + } + + +} + + +void btGImpactCollisionAlgorithm::gimpact_vs_shape_find_pairs( + const btTransform & trans0, + const btTransform & trans1, + btGImpactShapeInterface * shape0, + btCollisionShape * shape1, + btAlignedObjectArray & collided_primitives) +{ + + btAABB boxshape; + + + if(shape0->hasBoxSet()) + { + btTransform trans1to0 = trans0.inverse(); + trans1to0 *= trans1; + + shape1->getAabb(trans1to0,boxshape.m_min,boxshape.m_max); + + shape0->getBoxSet()->boxQuery(boxshape, collided_primitives); + } + else + { + shape1->getAabb(trans1,boxshape.m_min,boxshape.m_max); + + btAABB boxshape0; + int i = shape0->getNumChildShapes(); + + while(i--) + { + shape0->getChildAabb(i,trans0,boxshape0.m_min,boxshape0.m_max); + + if(boxshape.has_collision(boxshape0)) + { + collided_primitives.push_back(i); + } + } + + } + +} + + +void btGImpactCollisionAlgorithm::collide_gjk_triangles(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactMeshShapePart * shape0, + btGImpactMeshShapePart * shape1, + const int * pairs, int pair_count) +{ + btTriangleShapeEx tri0; + btTriangleShapeEx tri1; + + shape0->lockChildShapes(); + shape1->lockChildShapes(); + + const int * pair_pointer = pairs; + + while(pair_count--) + { + + m_triface0 = *(pair_pointer); + m_triface1 = *(pair_pointer+1); + pair_pointer+=2; + + + + shape0->getBulletTriangle(m_triface0,tri0); + shape1->getBulletTriangle(m_triface1,tri1); + + + //collide two convex shapes + if(tri0.overlap_test_conservative(tri1)) + { + convex_vs_convex_collision(body0,body1,&tri0,&tri1); + } + + } + + shape0->unlockChildShapes(); + shape1->unlockChildShapes(); +} + +void btGImpactCollisionAlgorithm::collide_sat_triangles(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactMeshShapePart * shape0, + btGImpactMeshShapePart * shape1, + const int * pairs, int pair_count) +{ + btTransform orgtrans0 = body0->getWorldTransform(); + btTransform orgtrans1 = body1->getWorldTransform(); + + btPrimitiveTriangle ptri0; + btPrimitiveTriangle ptri1; + BT_TRIANGLE_CONTACT contact_data; + + shape0->lockChildShapes(); + shape1->lockChildShapes(); + + const int * pair_pointer = pairs; + + while(pair_count--) + { + + m_triface0 = *(pair_pointer); + m_triface1 = *(pair_pointer+1); + pair_pointer+=2; + + + shape0->getPrimitiveTriangle(m_triface0,ptri0); + shape1->getPrimitiveTriangle(m_triface1,ptri1); + + #ifdef TRI_COLLISION_PROFILING + bt_begin_gim02_tri_time(); + #endif + + ptri0.applyTransform(orgtrans0); + ptri1.applyTransform(orgtrans1); + + + //build planes + ptri0.buildTriPlane(); + ptri1.buildTriPlane(); + // test conservative + + + + if(ptri0.overlap_test_conservative(ptri1)) + { + if(ptri0.find_triangle_collision_clip_method(ptri1,contact_data)) + { + + int j = contact_data.m_point_count; + while(j--) + { + + addContactPoint(body0, body1, + contact_data.m_points[j], + contact_data.m_separating_normal, + -contact_data.m_penetration_depth); + } + } + } + + #ifdef TRI_COLLISION_PROFILING + bt_end_gim02_tri_time(); + #endif + + } + + shape0->unlockChildShapes(); + shape1->unlockChildShapes(); + +} + + +void btGImpactCollisionAlgorithm::gimpact_vs_gimpact( + btCollisionObject * body0, + btCollisionObject * body1, + btGImpactShapeInterface * shape0, + btGImpactShapeInterface * shape1) +{ + + if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE) + { + btGImpactMeshShape * meshshape0 = static_cast(shape0); + m_part0 = meshshape0->getMeshPartCount(); + + while(m_part0--) + { + gimpact_vs_gimpact(body0,body1,meshshape0->getMeshPart(m_part0),shape1); + } + + return; + } + + if(shape1->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE) + { + btGImpactMeshShape * meshshape1 = static_cast(shape1); + m_part1 = meshshape1->getMeshPartCount(); + + while(m_part1--) + { + + gimpact_vs_gimpact(body0,body1,shape0,meshshape1->getMeshPart(m_part1)); + + } + + return; + } + + + btTransform orgtrans0 = body0->getWorldTransform(); + btTransform orgtrans1 = body1->getWorldTransform(); + + btPairSet pairset; + + gimpact_vs_gimpact_find_pairs(orgtrans0,orgtrans1,shape0,shape1,pairset); + + if(pairset.size()== 0) return; + + if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART && + shape1->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART) + { + btGImpactMeshShapePart * shapepart0 = static_cast(shape0); + btGImpactMeshShapePart * shapepart1 = static_cast(shape1); + //specialized function + #ifdef BULLET_TRIANGLE_COLLISION + collide_gjk_triangles(body0,body1,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size()); + #else + collide_sat_triangles(body0,body1,shapepart0,shapepart1,&pairset[0].m_index1,pairset.size()); + #endif + + return; + } + + //general function + + shape0->lockChildShapes(); + shape1->lockChildShapes(); + + GIM_ShapeRetriever retriever0(shape0); + GIM_ShapeRetriever retriever1(shape1); + + bool child_has_transform0 = shape0->childrenHasTransform(); + bool child_has_transform1 = shape1->childrenHasTransform(); + + int i = pairset.size(); + while(i--) + { + BT_PAIR * pair = &pairset[i]; + m_triface0 = pair->m_index1; + m_triface1 = pair->m_index2; + btCollisionShape * colshape0 = retriever0.getChildShape(m_triface0); + btCollisionShape * colshape1 = retriever1.getChildShape(m_triface1); + + if(child_has_transform0) + { + body0->setWorldTransform(orgtrans0*shape0->getChildTransform(m_triface0)); + } + + if(child_has_transform1) + { + body1->setWorldTransform(orgtrans1*shape1->getChildTransform(m_triface1)); + } + + //collide two convex shapes + convex_vs_convex_collision(body0,body1,colshape0,colshape1); + + + if(child_has_transform0) + { + body0->setWorldTransform(orgtrans0); + } + + if(child_has_transform1) + { + body1->setWorldTransform(orgtrans1); + } + + } + + shape0->unlockChildShapes(); + shape1->unlockChildShapes(); +} + +void btGImpactCollisionAlgorithm::gimpact_vs_shape(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactShapeInterface * shape0, + btCollisionShape * shape1,bool swapped) +{ + if(shape0->getGImpactShapeType()==CONST_GIMPACT_TRIMESH_SHAPE) + { + btGImpactMeshShape * meshshape0 = static_cast(shape0); + m_part0 = meshshape0->getMeshPartCount(); + + while(m_part0--) + { + + gimpact_vs_shape(body0, + body1, + meshshape0->getMeshPart(m_part0), + shape1,swapped); + + } + + return; + } + + #ifdef GIMPACT_VS_PLANE_COLLISION + if(shape0->getGImpactShapeType() == CONST_GIMPACT_TRIMESH_SHAPE_PART && + shape1->getShapeType() == STATIC_PLANE_PROXYTYPE) + { + btGImpactMeshShapePart * shapepart = static_cast(shape0); + btStaticPlaneShape * planeshape = static_cast(shape1); + gimpacttrimeshpart_vs_plane_collision(body0,body1,shapepart,planeshape,swapped); + return; + } + + #endif + + + + if(shape1->isCompound()) + { + btCompoundShape * compoundshape = static_cast(shape1); + gimpact_vs_compoundshape(body0,body1,shape0,compoundshape,swapped); + return; + } + else if(shape1->isConcave()) + { + btConcaveShape * concaveshape = static_cast(shape1); + gimpact_vs_concave(body0,body1,shape0,concaveshape,swapped); + return; + } + + + btTransform orgtrans0 = body0->getWorldTransform(); + + btTransform orgtrans1 = body1->getWorldTransform(); + + btAlignedObjectArray collided_results; + + gimpact_vs_shape_find_pairs(orgtrans0,orgtrans1,shape0,shape1,collided_results); + + if(collided_results.size() == 0) return; + + + shape0->lockChildShapes(); + + GIM_ShapeRetriever retriever0(shape0); + + + bool child_has_transform0 = shape0->childrenHasTransform(); + + + int i = collided_results.size(); + + while(i--) + { + int child_index = collided_results[i]; + if(swapped) + m_triface1 = child_index; + else + m_triface0 = child_index; + + btCollisionShape * colshape0 = retriever0.getChildShape(child_index); + + if(child_has_transform0) + { + body0->setWorldTransform(orgtrans0*shape0->getChildTransform(child_index)); + } + + //collide two shapes + if(swapped) + { + shape_vs_shape_collision(body1,body0,shape1,colshape0); + } + else + { + shape_vs_shape_collision(body0,body1,colshape0,shape1); + } + + //restore transforms + if(child_has_transform0) + { + body0->setWorldTransform(orgtrans0); + } + + } + + shape0->unlockChildShapes(); + +} + +void btGImpactCollisionAlgorithm::gimpact_vs_compoundshape(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactShapeInterface * shape0, + btCompoundShape * shape1,bool swapped) +{ + btTransform orgtrans1 = body1->getWorldTransform(); + + int i = shape1->getNumChildShapes(); + while(i--) + { + + btCollisionShape * colshape1 = shape1->getChildShape(i); + btTransform childtrans1 = orgtrans1*shape1->getChildTransform(i); + + body1->setWorldTransform(childtrans1); + + //collide child shape + gimpact_vs_shape(body0, body1, + shape0,colshape1,swapped); + + + //restore transforms + body1->setWorldTransform(orgtrans1); + } +} + +void btGImpactCollisionAlgorithm::gimpacttrimeshpart_vs_plane_collision( + btCollisionObject * body0, + btCollisionObject * body1, + btGImpactMeshShapePart * shape0, + btStaticPlaneShape * shape1,bool swapped) +{ + + + btTransform orgtrans0 = body0->getWorldTransform(); + btTransform orgtrans1 = body1->getWorldTransform(); + + btPlaneShape * planeshape = static_cast(shape1); + btVector4 plane; + planeshape->get_plane_equation_transformed(orgtrans1,plane); + + //test box against plane + + btAABB tribox; + shape0->getAabb(orgtrans0,tribox.m_min,tribox.m_max); + tribox.increment_margin(planeshape->getMargin()); + + if( tribox.plane_classify(plane)!= BT_CONST_COLLIDE_PLANE) return; + + shape0->lockChildShapes(); + + btScalar margin = shape0->getMargin() + planeshape->getMargin(); + + btVector3 vertex; + int vi = shape0->getVertexCount(); + while(vi--) + { + shape0->getVertex(vi,vertex); + vertex = orgtrans0(vertex); + + btScalar distance = vertex.dot(plane) - plane[3] - margin; + + if(distance<0.0)//add contact + { + if(swapped) + { + addContactPoint(body1, body0, + vertex, + -plane, + distance); + } + else + { + addContactPoint(body0, body1, + vertex, + plane, + distance); + } + } + } + + shape0->unlockChildShapes(); +} + + + + +class btGImpactTriangleCallback: public btTriangleCallback +{ +public: + btGImpactCollisionAlgorithm * algorithm; + btCollisionObject * body0; + btCollisionObject * body1; + btGImpactShapeInterface * gimpactshape0; + bool swapped; + btScalar margin; + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + btTriangleShapeEx tri1(triangle[0],triangle[1],triangle[2]); + tri1.setMargin(margin); + if(swapped) + { + algorithm->setPart0(partId); + algorithm->setFace0(triangleIndex); + } + else + { + algorithm->setPart1(partId); + algorithm->setFace1(triangleIndex); + } + algorithm->gimpact_vs_shape( + body0,body1,gimpactshape0,&tri1,swapped); + } +}; + + + + +void btGImpactCollisionAlgorithm::gimpact_vs_concave( + btCollisionObject * body0, + btCollisionObject * body1, + btGImpactShapeInterface * shape0, + btConcaveShape * shape1,bool swapped) +{ + //create the callback + btGImpactTriangleCallback tricallback; + tricallback.algorithm = this; + tricallback.body0 = body0; + tricallback.body1 = body1; + tricallback.gimpactshape0 = shape0; + tricallback.swapped = swapped; + tricallback.margin = shape1->getMargin(); + + //getting the trimesh AABB + btTransform gimpactInConcaveSpace; + + gimpactInConcaveSpace = body1->getWorldTransform().inverse() * body0->getWorldTransform(); + + btVector3 minAABB,maxAABB; + shape0->getAabb(gimpactInConcaveSpace,minAABB,maxAABB); + + shape1->processAllTriangles(&tricallback,minAABB,maxAABB); + +} + + + +void btGImpactCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + clearCache(); + + m_resultOut = resultOut; + m_dispatchInfo = &dispatchInfo; + btGImpactShapeInterface * gimpactshape0; + btGImpactShapeInterface * gimpactshape1; + + if (body0->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE) + { + gimpactshape0 = static_cast(body0->getCollisionShape()); + + if( body1->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE ) + { + gimpactshape1 = static_cast(body1->getCollisionShape()); + + gimpact_vs_gimpact(body0,body1,gimpactshape0,gimpactshape1); + } + else + { + gimpact_vs_shape(body0,body1,gimpactshape0,body1->getCollisionShape(),false); + } + + } + else if (body1->getCollisionShape()->getShapeType()==GIMPACT_SHAPE_PROXYTYPE ) + { + gimpactshape1 = static_cast(body1->getCollisionShape()); + + gimpact_vs_shape(body1,body0,gimpactshape1,body0->getCollisionShape(),true); + } +} + + +btScalar btGImpactCollisionAlgorithm::calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) +{ + return 1.f; + +} + +///////////////////////////////////// REGISTERING ALGORITHM ////////////////////////////////////////////// + +btGImpactCollisionAlgorithm::CreateFunc g_gimpact_cf; + +//! Use this function for register the algorithm externally +void btGImpactCollisionAlgorithm::registerAlgorithm(btCollisionDispatcher * dispatcher) +{ + + int i; + + for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ ) + { + dispatcher->registerCollisionCreateFunc(GIMPACT_SHAPE_PROXYTYPE,i ,&g_gimpact_cf); + } + + for ( i = 0;i < MAX_BROADPHASE_COLLISION_TYPES ;i++ ) + { + dispatcher->registerCollisionCreateFunc(i,GIMPACT_SHAPE_PROXYTYPE ,&g_gimpact_cf); + } + +} diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h new file mode 100644 index 00000000000..8998cd06cf0 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h @@ -0,0 +1,306 @@ +/*! \file btGImpactShape.h +\author Francisco León Nájera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef BVH_CONCAVE_COLLISION_ALGORITHM_H +#define BVH_CONCAVE_COLLISION_ALGORITHM_H + +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +#include "BulletCollision/BroadphaseCollision/btDispatcher.h" +#include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h" +#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" +class btDispatcher; +#include "BulletCollision/BroadphaseCollision/btBroadphaseProxy.h" +#include "BulletCollision/CollisionDispatch/btCollisionCreateFunc.h" +#include "BulletCollision/CollisionDispatch/btCollisionDispatcher.h" + +#include "LinearMath/btAlignedObjectArray.h" + +#include "btGImpactShape.h" +#include "BulletCollision/CollisionShapes/btStaticPlaneShape.h" +#include "BulletCollision/CollisionShapes/btCompoundShape.h" +#include "BulletCollision/CollisionDispatch/btConvexConvexAlgorithm.h" +#include "LinearMath/btIDebugDraw.h" + + + +//! Collision Algorithm for GImpact Shapes +/*! +For register this algorithm in Bullet, proceed as following: + \code +btCollisionDispatcher * dispatcher = static_cast(m_dynamicsWorld ->getDispatcher()); +btGImpactCollisionAlgorithm::registerAlgorithm(dispatcher); + \endcode +*/ +class btGImpactCollisionAlgorithm : public btCollisionAlgorithm +{ +protected: + btCollisionAlgorithm * m_convex_algorithm; + btPersistentManifold * m_manifoldPtr; + btManifoldResult* m_resultOut; + const btDispatcherInfo * m_dispatchInfo; + int m_triface0; + int m_part0; + int m_triface1; + int m_part1; + + + //! Creates a new contact point + SIMD_FORCE_INLINE btPersistentManifold* newContactManifold(btCollisionObject* body0,btCollisionObject* body1) + { + m_manifoldPtr = m_dispatcher->getNewManifold(body0,body1); + return m_manifoldPtr; + } + + SIMD_FORCE_INLINE void destroyConvexAlgorithm() + { + if(m_convex_algorithm) + { + m_convex_algorithm->~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm( m_convex_algorithm); + m_convex_algorithm = NULL; + } + } + + SIMD_FORCE_INLINE void destroyContactManifolds() + { + if(m_manifoldPtr == NULL) return; + m_dispatcher->releaseManifold(m_manifoldPtr); + m_manifoldPtr = NULL; + } + + SIMD_FORCE_INLINE void clearCache() + { + destroyContactManifolds(); + destroyConvexAlgorithm(); + + m_triface0 = -1; + m_part0 = -1; + m_triface1 = -1; + m_part1 = -1; + } + + SIMD_FORCE_INLINE btPersistentManifold* getLastManifold() + { + return m_manifoldPtr; + } + + + // Call before process collision + SIMD_FORCE_INLINE void checkManifold(btCollisionObject* body0,btCollisionObject* body1) + { + if(getLastManifold() == 0) + { + newContactManifold(body0,body1); + } + + m_resultOut->setPersistentManifold(getLastManifold()); + } + + // Call before process collision + SIMD_FORCE_INLINE btCollisionAlgorithm * newAlgorithm(btCollisionObject* body0,btCollisionObject* body1) + { + checkManifold(body0,body1); + + btCollisionAlgorithm * convex_algorithm = m_dispatcher->findAlgorithm( + body0,body1,getLastManifold()); + return convex_algorithm ; + } + + // Call before process collision + SIMD_FORCE_INLINE void checkConvexAlgorithm(btCollisionObject* body0,btCollisionObject* body1) + { + if(m_convex_algorithm) return; + m_convex_algorithm = newAlgorithm(body0,body1); + } + + + + + void addContactPoint(btCollisionObject * body0, + btCollisionObject * body1, + const btVector3 & point, + const btVector3 & normal, + btScalar distance); + +//! Collision routines +//!@{ + + void collide_gjk_triangles(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactMeshShapePart * shape0, + btGImpactMeshShapePart * shape1, + const int * pairs, int pair_count); + + void collide_sat_triangles(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactMeshShapePart * shape0, + btGImpactMeshShapePart * shape1, + const int * pairs, int pair_count); + + + + + void shape_vs_shape_collision( + btCollisionObject * body0, + btCollisionObject * body1, + btCollisionShape * shape0, + btCollisionShape * shape1); + + void convex_vs_convex_collision(btCollisionObject * body0, + btCollisionObject * body1, + btCollisionShape * shape0, + btCollisionShape * shape1); + + + + void gimpact_vs_gimpact_find_pairs( + const btTransform & trans0, + const btTransform & trans1, + btGImpactShapeInterface * shape0, + btGImpactShapeInterface * shape1,btPairSet & pairset); + + void gimpact_vs_shape_find_pairs( + const btTransform & trans0, + const btTransform & trans1, + btGImpactShapeInterface * shape0, + btCollisionShape * shape1, + btAlignedObjectArray & collided_primitives); + + + void gimpacttrimeshpart_vs_plane_collision( + btCollisionObject * body0, + btCollisionObject * body1, + btGImpactMeshShapePart * shape0, + btStaticPlaneShape * shape1,bool swapped); + + +public: + + btGImpactCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1); + + virtual ~btGImpactCollisionAlgorithm(); + + virtual void processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + btScalar calculateTimeOfImpact(btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut); + + virtual void getAllContactManifolds(btManifoldArray& manifoldArray) + { + if (m_manifoldPtr) + manifoldArray.push_back(m_manifoldPtr); + } + + + struct CreateFunc :public btCollisionAlgorithmCreateFunc + { + virtual btCollisionAlgorithm* CreateCollisionAlgorithm(btCollisionAlgorithmConstructionInfo& ci, btCollisionObject* body0,btCollisionObject* body1) + { + void* mem = ci.m_dispatcher1->allocateCollisionAlgorithm(sizeof(btGImpactCollisionAlgorithm)); + return new(mem) btGImpactCollisionAlgorithm(ci,body0,body1); + } + }; + + //! Use this function for register the algorithm externally + static void registerAlgorithm(btCollisionDispatcher * dispatcher); + + //! Gets the average time in miliseconds of tree collisions + static float getAverageTreeCollisionTime(); + + //! Gets the average time in miliseconds of triangle collisions + static float getAverageTriangleCollisionTime(); + + + //! Collides two gimpact shapes + /*! + \pre shape0 and shape1 couldn't be btGImpactMeshShape objects + */ + + + void gimpact_vs_gimpact(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactShapeInterface * shape0, + btGImpactShapeInterface * shape1); + + void gimpact_vs_shape(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactShapeInterface * shape0, + btCollisionShape * shape1,bool swapped); + + void gimpact_vs_compoundshape(btCollisionObject * body0, + btCollisionObject * body1, + btGImpactShapeInterface * shape0, + btCompoundShape * shape1,bool swapped); + + void gimpact_vs_concave( + btCollisionObject * body0, + btCollisionObject * body1, + btGImpactShapeInterface * shape0, + btConcaveShape * shape1,bool swapped); + + + + + /// Accessor/Mutator pairs for Part and triangleID + void setFace0(int value) + { + m_triface0 = value; + } + int getFace0() + { + return m_triface0; + } + void setFace1(int value) + { + m_triface1 = value; + } + int getFace1() + { + return m_triface1; + } + void setPart0(int value) + { + m_part0 = value; + } + int getPart0() + { + return m_part0; + } + void setPart1(int value) + { + m_part1 = value; + } + int getPart1() + { + return m_part1; + } + +}; + + +//algorithm details +//#define BULLET_TRIANGLE_COLLISION 1 +#define GIMPACT_VS_PLANE_COLLISION 1 + + + +#endif //BVH_CONCAVE_COLLISION_ALGORITHM_H diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactMassUtil.h b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactMassUtil.h new file mode 100644 index 00000000000..b3c40569f23 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactMassUtil.h @@ -0,0 +1,60 @@ +/*! \file btGImpactMassUtil.h +\author Francisco León Nájera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef GIMPACT_MASS_UTIL_H +#define GIMPACT_MASS_UTIL_H + +#include "LinearMath/btTransform.h" + + + +SIMD_FORCE_INLINE btVector3 gim_inertia_add_transformed( + const btVector3 & source_inertia, const btVector3 & added_inertia, const btTransform & transform) +{ + btMatrix3x3 rotatedTensor = transform.getBasis().scaled(added_inertia) * transform.getBasis().transpose(); + + btScalar x2 = transform.getOrigin()[0]; + x2*= x2; + btScalar y2 = transform.getOrigin()[1]; + y2*= y2; + btScalar z2 = transform.getOrigin()[2]; + z2*= z2; + + btScalar ix = rotatedTensor[0][0]*(y2+z2); + btScalar iy = rotatedTensor[1][1]*(x2+z2); + btScalar iz = rotatedTensor[2][2]*(x2+y2); + + return btVector3(source_inertia[0]+ix,source_inertia[1]+iy,source_inertia[2] + iz); +} + +SIMD_FORCE_INLINE btVector3 gim_get_point_inertia(const btVector3 & point, btScalar mass) +{ + btScalar x2 = point[0]*point[0]; + btScalar y2 = point[1]*point[1]; + btScalar z2 = point[2]*point[2]; + return btVector3(mass*(y2+z2),mass*(x2+z2),mass*(x2+y2)); +} + + +#endif //GIMPACT_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp new file mode 100644 index 00000000000..957cc97df9c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.cpp @@ -0,0 +1,529 @@ +/*! \file gim_box_set.h +\author Francisco León Nájera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btGImpactQuantizedBvh.h" +#include "LinearMath/btQuickprof.h" + +#ifdef TRI_COLLISION_PROFILING +btClock g_q_tree_clock; + + +float g_q_accum_tree_collision_time = 0; +int g_q_count_traversing = 0; + + +void bt_begin_gim02_q_tree_time() +{ + g_q_tree_clock.reset(); +} + +void bt_end_gim02_q_tree_time() +{ + g_q_accum_tree_collision_time += g_q_tree_clock.getTimeMicroseconds(); + g_q_count_traversing++; +} + + +//! Gets the average time in miliseconds of tree collisions +float btGImpactQuantizedBvh::getAverageTreeCollisionTime() +{ + if(g_q_count_traversing == 0) return 0; + + float avgtime = g_q_accum_tree_collision_time; + avgtime /= (float)g_q_count_traversing; + + g_q_accum_tree_collision_time = 0; + g_q_count_traversing = 0; + return avgtime; + +// float avgtime = g_q_count_traversing; +// g_q_count_traversing = 0; +// return avgtime; + +} + +#endif //TRI_COLLISION_PROFILING + +/////////////////////// btQuantizedBvhTree ///////////////////////////////// + +void btQuantizedBvhTree::calc_quantization( + BT_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin) +{ + //calc globa box + btAABB global_bound; + global_bound.invalidate(); + + for (int i=0;i splitValue) + { + //swap + primitive_boxes.swap(i,splitIndex); + //swapLeafNodes(i,splitIndex); + splitIndex++; + } + } + + //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex + //otherwise the tree-building might fail due to stack-overflows in certain cases. + //unbalanced1 is unsafe: it can cause stack overflows + //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); + + //unbalanced2 should work too: always use center (perfect balanced trees) + //bool unbalanced2 = true; + + //this should be safe too: + int rangeBalancedIndices = numIndices/3; + bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); + + if (unbalanced) + { + splitIndex = startIndex+ (numIndices>>1); + } + + bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); + btAssert(!unbal); + + return splitIndex; + +} + + +void btQuantizedBvhTree::_build_sub_tree(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex) +{ + int curIndex = m_num_nodes; + m_num_nodes++; + + btAssert((endIndex-startIndex)>0); + + if ((endIndex-startIndex)==1) + { + //We have a leaf node + setNodeBound(curIndex,primitive_boxes[startIndex].m_bound); + m_node_array[curIndex].setDataIndex(primitive_boxes[startIndex].m_data); + + return; + } + //calculate Best Splitting Axis and where to split it. Sort the incoming 'leafNodes' array within range 'startIndex/endIndex'. + + //split axis + int splitIndex = _calc_splitting_axis(primitive_boxes,startIndex,endIndex); + + splitIndex = _sort_and_calc_splitting_index( + primitive_boxes,startIndex,endIndex, + splitIndex//split axis + ); + + + //calc this node bounding box + + btAABB node_bound; + node_bound.invalidate(); + + for (int i=startIndex;iget_primitive_box(getNodeData(nodecount),leafbox); + setNodeBound(nodecount,leafbox); + } + else + { + //const BT_BVH_TREE_NODE * nodepointer = get_node_pointer(nodecount); + //get left bound + btAABB bound; + bound.invalidate(); + + btAABB temp_box; + + int child_node = getLeftNode(nodecount); + if(child_node) + { + getNodeBound(child_node,temp_box); + bound.merge(temp_box); + } + + child_node = getRightNode(nodecount); + if(child_node) + { + getNodeBound(child_node,temp_box); + bound.merge(temp_box); + } + + setNodeBound(nodecount,bound); + } + } +} + +//! this rebuild the entire set +void btGImpactQuantizedBvh::buildSet() +{ + //obtain primitive boxes + BT_BVH_DATA_ARRAY primitive_boxes; + primitive_boxes.resize(m_primitive_manager->get_primitive_count()); + + for (int i = 0;iget_primitive_box(i,primitive_boxes[i].m_bound); + primitive_boxes[i].m_data = i; + } + + m_box_tree.build_tree(primitive_boxes); +} + +//! returns the indices of the primitives in the m_primitive_manager +bool btGImpactQuantizedBvh::boxQuery(const btAABB & box, btAlignedObjectArray & collided_results) const +{ + int curIndex = 0; + int numNodes = getNodeCount(); + + //quantize box + + unsigned short quantizedMin[3]; + unsigned short quantizedMax[3]; + + m_box_tree.quantizePoint(quantizedMin,box.m_min); + m_box_tree.quantizePoint(quantizedMax,box.m_max); + + + while (curIndex < numNodes) + { + + //catch bugs in tree data + + bool aabbOverlap = m_box_tree.testQuantizedBoxOverlapp(curIndex, quantizedMin,quantizedMax); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData(curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getEscapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; +} + + + +//! returns the indices of the primitives in the m_primitive_manager +bool btGImpactQuantizedBvh::rayQuery( + const btVector3 & ray_dir,const btVector3 & ray_origin , + btAlignedObjectArray & collided_results) const +{ + int curIndex = 0; + int numNodes = getNodeCount(); + + while (curIndex < numNodes) + { + btAABB bound; + getNodeBound(curIndex,bound); + + //catch bugs in tree data + + bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData( curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getEscapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; +} + + +SIMD_FORCE_INLINE bool _quantized_node_collision( + btGImpactQuantizedBvh * boxset0, btGImpactQuantizedBvh * boxset1, + const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0, + int node0 ,int node1, bool complete_primitive_tests) +{ + btAABB box0; + boxset0->getNodeBound(node0,box0); + btAABB box1; + boxset1->getNodeBound(node1,box1); + + return box0.overlapping_trans_cache(box1,trans_cache_1to0,complete_primitive_tests ); +// box1.appy_transform_trans_cache(trans_cache_1to0); +// return box0.has_collision(box1); + +} + + +//stackless recursive collision routine +static void _find_quantized_collision_pairs_recursive( + btGImpactQuantizedBvh * boxset0, btGImpactQuantizedBvh * boxset1, + btPairSet * collision_pairs, + const BT_BOX_BOX_TRANSFORM_CACHE & trans_cache_1to0, + int node0, int node1, bool complete_primitive_tests) +{ + + + + if( _quantized_node_collision( + boxset0,boxset1,trans_cache_1to0, + node0,node1,complete_primitive_tests) ==false) return;//avoid colliding internal nodes + + if(boxset0->isLeafNode(node0)) + { + if(boxset1->isLeafNode(node1)) + { + // collision result + collision_pairs->push_pair( + boxset0->getNodeData(node0),boxset1->getNodeData(node1)); + return; + } + else + { + + //collide left recursive + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + node0,boxset1->getLeftNode(node1),false); + + //collide right recursive + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + node0,boxset1->getRightNode(node1),false); + + + } + } + else + { + if(boxset1->isLeafNode(node1)) + { + + //collide left recursive + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),node1,false); + + + //collide right recursive + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),node1,false); + + + } + else + { + //collide left0 left1 + + + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),boxset1->getLeftNode(node1),false); + + //collide left0 right1 + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getLeftNode(node0),boxset1->getRightNode(node1),false); + + + //collide right0 left1 + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),boxset1->getLeftNode(node1),false); + + //collide right0 right1 + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + collision_pairs,trans_cache_1to0, + boxset0->getRightNode(node0),boxset1->getRightNode(node1),false); + + }// else if node1 is not a leaf + }// else if node0 is not a leaf +} + + +void btGImpactQuantizedBvh::find_collision(btGImpactQuantizedBvh * boxset0, const btTransform & trans0, + btGImpactQuantizedBvh * boxset1, const btTransform & trans1, + btPairSet & collision_pairs) +{ + + if(boxset0->getNodeCount()==0 || boxset1->getNodeCount()==0 ) return; + + BT_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0; + + trans_cache_1to0.calc_from_homogenic(trans0,trans1); + +#ifdef TRI_COLLISION_PROFILING + bt_begin_gim02_q_tree_time(); +#endif //TRI_COLLISION_PROFILING + + _find_quantized_collision_pairs_recursive( + boxset0,boxset1, + &collision_pairs,trans_cache_1to0,0,0,true); +#ifdef TRI_COLLISION_PROFILING + bt_end_gim02_q_tree_time(); +#endif //TRI_COLLISION_PROFILING + +} + + diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h new file mode 100644 index 00000000000..e9e60c7348d --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactQuantizedBvh.h @@ -0,0 +1,379 @@ +#ifndef GIM_QUANTIZED_SET_H_INCLUDED +#define GIM_QUANTIZED_SET_H_INCLUDED + +/*! \file btGImpactQuantizedBvh.h +\author Francisco León Nájera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btGImpactBvh.h" +#include "btQuantization.h" + + + +/*! \defgroup BOX_TREES + + + +*/ +//! @{ + + +///btQuantizedBvhNode is a compressed aabb node, 16 bytes. +///Node can be used for leafnode or internal node. Leafnodes can point to 32-bit triangle index (non-negative range). +ATTRIBUTE_ALIGNED16 (struct) BT_QUANTIZED_BVH_NODE +{ + //12 bytes + unsigned short int m_quantizedAabbMin[3]; + unsigned short int m_quantizedAabbMax[3]; + //4 bytes + int m_escapeIndexOrDataIndex; + + BT_QUANTIZED_BVH_NODE() + { + m_escapeIndexOrDataIndex = 0; + } + + SIMD_FORCE_INLINE bool isLeafNode() const + { + //skipindex is negative (internal node), triangleindex >=0 (leafnode) + return (m_escapeIndexOrDataIndex>=0); + } + + SIMD_FORCE_INLINE int getEscapeIndex() const + { + //btAssert(m_escapeIndexOrDataIndex < 0); + return -m_escapeIndexOrDataIndex; + } + + SIMD_FORCE_INLINE void setEscapeIndex(int index) + { + m_escapeIndexOrDataIndex = -index; + } + + SIMD_FORCE_INLINE int getDataIndex() const + { + //btAssert(m_escapeIndexOrDataIndex >= 0); + + return m_escapeIndexOrDataIndex; + } + + SIMD_FORCE_INLINE void setDataIndex(int index) + { + m_escapeIndexOrDataIndex = index; + } + + SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp( + unsigned short * quantizedMin,unsigned short * quantizedMax) const + { + if(m_quantizedAabbMin[0] > quantizedMax[0] || + m_quantizedAabbMax[0] < quantizedMin[0] || + m_quantizedAabbMin[1] > quantizedMax[1] || + m_quantizedAabbMax[1] < quantizedMin[1] || + m_quantizedAabbMin[2] > quantizedMax[2] || + m_quantizedAabbMax[2] < quantizedMin[2]) + { + return false; + } + return true; + } + +}; + + + +class BT_QUANTIZED_BVH_NODE_ARRAY:public btAlignedObjectArray +{ +}; + + + + +//! Basic Box tree structure +class btQuantizedBvhTree +{ +protected: + int m_num_nodes; + BT_QUANTIZED_BVH_NODE_ARRAY m_node_array; + btAABB m_global_bound; + btVector3 m_bvhQuantization; +protected: + void calc_quantization(BT_BVH_DATA_ARRAY & primitive_boxes, btScalar boundMargin = btScalar(1.0) ); + + int _sort_and_calc_splitting_index( + BT_BVH_DATA_ARRAY & primitive_boxes, + int startIndex, int endIndex, int splitAxis); + + int _calc_splitting_axis(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); + + void _build_sub_tree(BT_BVH_DATA_ARRAY & primitive_boxes, int startIndex, int endIndex); +public: + btQuantizedBvhTree() + { + m_num_nodes = 0; + } + + //! prototype functions for box tree management + //!@{ + void build_tree(BT_BVH_DATA_ARRAY & primitive_boxes); + + SIMD_FORCE_INLINE void quantizePoint( + unsigned short * quantizedpoint, const btVector3 & point) const + { + bt_quantize_clamp(quantizedpoint,point,m_global_bound.m_min,m_global_bound.m_max,m_bvhQuantization); + } + + + SIMD_FORCE_INLINE bool testQuantizedBoxOverlapp( + int node_index, + unsigned short * quantizedMin,unsigned short * quantizedMax) const + { + return m_node_array[node_index].testQuantizedBoxOverlapp(quantizedMin,quantizedMax); + } + + SIMD_FORCE_INLINE void clearNodes() + { + m_node_array.clear(); + m_num_nodes = 0; + } + + //! node count + SIMD_FORCE_INLINE int getNodeCount() const + { + return m_num_nodes; + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const + { + return m_node_array[nodeindex].isLeafNode(); + } + + SIMD_FORCE_INLINE int getNodeData(int nodeindex) const + { + return m_node_array[nodeindex].getDataIndex(); + } + + SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const + { + bound.m_min = bt_unquantize( + m_node_array[nodeindex].m_quantizedAabbMin, + m_global_bound.m_min,m_bvhQuantization); + + bound.m_max = bt_unquantize( + m_node_array[nodeindex].m_quantizedAabbMax, + m_global_bound.m_min,m_bvhQuantization); + } + + SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound) + { + bt_quantize_clamp( m_node_array[nodeindex].m_quantizedAabbMin, + bound.m_min, + m_global_bound.m_min, + m_global_bound.m_max, + m_bvhQuantization); + + bt_quantize_clamp( m_node_array[nodeindex].m_quantizedAabbMax, + bound.m_max, + m_global_bound.m_min, + m_global_bound.m_max, + m_bvhQuantization); + } + + SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const + { + return nodeindex+1; + } + + SIMD_FORCE_INLINE int getRightNode(int nodeindex) const + { + if(m_node_array[nodeindex+1].isLeafNode()) return nodeindex+2; + return nodeindex+1 + m_node_array[nodeindex+1].getEscapeIndex(); + } + + SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const + { + return m_node_array[nodeindex].getEscapeIndex(); + } + + SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const + { + return &m_node_array[index]; + } + + //!@} +}; + + + +//! Structure for containing Boxes +/*! +This class offers an structure for managing a box tree of primitives. +Requires a Primitive prototype (like btPrimitiveManagerBase ) +*/ +class btGImpactQuantizedBvh +{ +protected: + btQuantizedBvhTree m_box_tree; + btPrimitiveManagerBase * m_primitive_manager; + +protected: + //stackless refit + void refit(); +public: + + //! this constructor doesn't build the tree. you must call buildSet + btGImpactQuantizedBvh() + { + m_primitive_manager = NULL; + } + + //! this constructor doesn't build the tree. you must call buildSet + btGImpactQuantizedBvh(btPrimitiveManagerBase * primitive_manager) + { + m_primitive_manager = primitive_manager; + } + + SIMD_FORCE_INLINE btAABB getGlobalBox() const + { + btAABB totalbox; + getNodeBound(0, totalbox); + return totalbox; + } + + SIMD_FORCE_INLINE void setPrimitiveManager(btPrimitiveManagerBase * primitive_manager) + { + m_primitive_manager = primitive_manager; + } + + SIMD_FORCE_INLINE btPrimitiveManagerBase * getPrimitiveManager() const + { + return m_primitive_manager; + } + + +//! node manager prototype functions +///@{ + + //! this attemps to refit the box set. + SIMD_FORCE_INLINE void update() + { + refit(); + } + + //! this rebuild the entire set + void buildSet(); + + //! returns the indices of the primitives in the m_primitive_manager + bool boxQuery(const btAABB & box, btAlignedObjectArray & collided_results) const; + + //! returns the indices of the primitives in the m_primitive_manager + SIMD_FORCE_INLINE bool boxQueryTrans(const btAABB & box, + const btTransform & transform, btAlignedObjectArray & collided_results) const + { + btAABB transbox=box; + transbox.appy_transform(transform); + return boxQuery(transbox,collided_results); + } + + //! returns the indices of the primitives in the m_primitive_manager + bool rayQuery( + const btVector3 & ray_dir,const btVector3 & ray_origin , + btAlignedObjectArray & collided_results) const; + + //! tells if this set has hierarcht + SIMD_FORCE_INLINE bool hasHierarchy() const + { + return true; + } + + //! tells if this set is a trimesh + SIMD_FORCE_INLINE bool isTrimesh() const + { + return m_primitive_manager->is_trimesh(); + } + + //! node count + SIMD_FORCE_INLINE int getNodeCount() const + { + return m_box_tree.getNodeCount(); + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(int nodeindex) const + { + return m_box_tree.isLeafNode(nodeindex); + } + + SIMD_FORCE_INLINE int getNodeData(int nodeindex) const + { + return m_box_tree.getNodeData(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeBound(int nodeindex, btAABB & bound) const + { + m_box_tree.getNodeBound(nodeindex, bound); + } + + SIMD_FORCE_INLINE void setNodeBound(int nodeindex, const btAABB & bound) + { + m_box_tree.setNodeBound(nodeindex, bound); + } + + + SIMD_FORCE_INLINE int getLeftNode(int nodeindex) const + { + return m_box_tree.getLeftNode(nodeindex); + } + + SIMD_FORCE_INLINE int getRightNode(int nodeindex) const + { + return m_box_tree.getRightNode(nodeindex); + } + + SIMD_FORCE_INLINE int getEscapeNodeIndex(int nodeindex) const + { + return m_box_tree.getEscapeNodeIndex(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeTriangle(int nodeindex,btPrimitiveTriangle & triangle) const + { + m_primitive_manager->get_primitive_triangle(getNodeData(nodeindex),triangle); + } + + + SIMD_FORCE_INLINE const BT_QUANTIZED_BVH_NODE * get_node_pointer(int index = 0) const + { + return m_box_tree.get_node_pointer(index); + } + +//! @} + + static float getAverageTreeCollisionTime(); + + + static void find_collision(btGImpactQuantizedBvh * boxset1, const btTransform & trans1, + btGImpactQuantizedBvh * boxset2, const btTransform & trans2, + btPairSet & collision_pairs); +}; + + +#endif // GIM_BOXPRUNING_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.cpp new file mode 100644 index 00000000000..da6a4dbfc28 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.cpp @@ -0,0 +1,183 @@ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#include "btGImpactShape.h" +#include "btGImpactMassUtil.h" + + +#define CALC_EXACT_INERTIA 1 + +void btGImpactCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + lockChildShapes(); +#ifdef CALC_EXACT_INERTIA + inertia.setValue(0.f,0.f,0.f); + + int i = this->getNumChildShapes(); + btScalar shapemass = mass/btScalar(i); + + while(i--) + { + btVector3 temp_inertia; + m_childShapes[i]->calculateLocalInertia(shapemass,temp_inertia); + if(childrenHasTransform()) + { + inertia = gim_inertia_add_transformed( inertia,temp_inertia,m_childTransforms[i]); + } + else + { + inertia = gim_inertia_add_transformed( inertia,temp_inertia,btTransform::getIdentity()); + } + + } + +#else + + // Calc box inertia + + btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0]; + btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1]; + btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2]; + const btScalar x2 = lx*lx; + const btScalar y2 = ly*ly; + const btScalar z2 = lz*lz; + const btScalar scaledmass = mass * btScalar(0.08333333); + + inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2)); + +#endif + unlockChildShapes(); +} + + + +void btGImpactMeshShapePart::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + lockChildShapes(); + + +#ifdef CALC_EXACT_INERTIA + inertia.setValue(0.f,0.f,0.f); + + int i = this->getVertexCount(); + btScalar pointmass = mass/btScalar(i); + + while(i--) + { + btVector3 pointintertia; + this->getVertex(i,pointintertia); + pointintertia = gim_get_point_inertia(pointintertia,pointmass); + inertia+=pointintertia; + } + +#else + + // Calc box inertia + + btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0]; + btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1]; + btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2]; + const btScalar x2 = lx*lx; + const btScalar y2 = ly*ly; + const btScalar z2 = lz*lz; + const btScalar scaledmass = mass * btScalar(0.08333333); + + inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2)); + +#endif + + unlockChildShapes(); +} + +void btGImpactMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + +#ifdef CALC_EXACT_INERTIA + inertia.setValue(0.f,0.f,0.f); + + int i = this->getMeshPartCount(); + btScalar partmass = mass/btScalar(i); + + while(i--) + { + btVector3 partinertia; + getMeshPart(i)->calculateLocalInertia(partmass,partinertia); + inertia+=partinertia; + } + +#else + + // Calc box inertia + + btScalar lx= m_localAABB.m_max[0] - m_localAABB.m_min[0]; + btScalar ly= m_localAABB.m_max[1] - m_localAABB.m_min[1]; + btScalar lz= m_localAABB.m_max[2] - m_localAABB.m_min[2]; + const btScalar x2 = lx*lx; + const btScalar y2 = ly*ly; + const btScalar z2 = lz*lz; + const btScalar scaledmass = mass * btScalar(0.08333333); + + inertia = scaledmass * (btVector3(y2+z2,x2+z2,x2+y2)); + +#endif +} + +void btGImpactMeshShape::rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const +{ +} + + +void btGImpactMeshShapePart::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + lockChildShapes(); + btAABB box; + box.m_min = aabbMin; + box.m_max = aabbMax; + + btAlignedObjectArray collided; + m_box_set.boxQuery(box,collided); + + if(collided.size()==0) + { + unlockChildShapes(); + return; + } + + int part = (int)getPart(); + btPrimitiveTriangle triangle; + int i = collided.size(); + while(i--) + { + this->getPrimitiveTriangle(collided[i],triangle); + callback->processTriangle(triangle.m_vertices,part,collided[i]); + } + unlockChildShapes(); + +} + +void btGImpactMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + int i = m_mesh_parts.size(); + while(i--) + { + m_mesh_parts[i]->processAllTriangles(callback,aabbMin,aabbMax); + } +} diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.h b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.h new file mode 100644 index 00000000000..2e16509457a --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGImpactShape.h @@ -0,0 +1,1109 @@ +/*! \file btGImpactShape.h +\author Francisco León Nájera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef GIMPACT_SHAPE_H +#define GIMPACT_SHAPE_H + +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "BulletCollision/CollisionShapes/btStridingMeshInterface.h" +#include "BulletCollision/CollisionShapes/btCollisionMargin.h" +#include "BulletCollision/CollisionDispatch/btCollisionWorld.h" +#include "BulletCollision/CollisionShapes/btConcaveShape.h" +#include "BulletCollision/CollisionShapes/btTetrahedronShape.h" +#include "LinearMath/btVector3.h" +#include "LinearMath/btTransform.h" +#include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btAlignedObjectArray.h" + +#include "btGImpactQuantizedBvh.h" // box tree class + + +//! declare Quantized trees, (you can change to float based trees) +typedef btGImpactQuantizedBvh btGImpactBoxSet; + +enum eGIMPACT_SHAPE_TYPE +{ + CONST_GIMPACT_COMPOUND_SHAPE = 0, + CONST_GIMPACT_TRIMESH_SHAPE_PART, + CONST_GIMPACT_TRIMESH_SHAPE +}; + + +//! Helper class for tetrahedrons +class btTetrahedronShapeEx:public btBU_Simplex1to4 +{ +public: + btTetrahedronShapeEx() + { + m_numVertices = 4; + } + + + SIMD_FORCE_INLINE void setVertices( + const btVector3 & v0,const btVector3 & v1, + const btVector3 & v2,const btVector3 & v3) + { + m_vertices[0] = v0; + m_vertices[1] = v1; + m_vertices[2] = v2; + m_vertices[3] = v3; + recalcLocalAabb(); + } +}; + + +//! Base class for gimpact shapes +class btGImpactShapeInterface : public btConcaveShape +{ +protected: + btAABB m_localAABB; + bool m_needs_update; + btVector3 localScaling; + btGImpactBoxSet m_box_set;// optionally boxset + + //! use this function for perfofm refit in bounding boxes + //! use this function for perfofm refit in bounding boxes + virtual void calcLocalAABB() + { + lockChildShapes(); + if(m_box_set.getNodeCount() == 0) + { + m_box_set.buildSet(); + } + else + { + m_box_set.update(); + } + unlockChildShapes(); + + m_localAABB = m_box_set.getGlobalBox(); + } + + +public: + btGImpactShapeInterface() + { + m_localAABB.invalidate(); + m_needs_update = true; + localScaling.setValue(1.f,1.f,1.f); + } + + + //! performs refit operation + /*! + Updates the entire Box set of this shape. + \pre postUpdate() must be called for attemps to calculating the box set, else this function + will does nothing. + \post if m_needs_update == true, then it calls calcLocalAABB(); + */ + SIMD_FORCE_INLINE void updateBound() + { + if(!m_needs_update) return; + calcLocalAABB(); + m_needs_update = false; + } + + //! If the Bounding box is not updated, then this class attemps to calculate it. + /*! + \post Calls updateBound() for update the box set. + */ + void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + btAABB transformedbox = m_localAABB; + transformedbox.appy_transform(t); + aabbMin = transformedbox.m_min; + aabbMax = transformedbox.m_max; + } + + //! Tells to this object that is needed to refit the box set + virtual void postUpdate() + { + m_needs_update = true; + } + + //! Obtains the local box, which is the global calculated box of the total of subshapes + SIMD_FORCE_INLINE const btAABB & getLocalBox() + { + return m_localAABB; + } + + + virtual int getShapeType() const + { + return GIMPACT_SHAPE_PROXYTYPE; + } + + /*! + \post You must call updateBound() for update the box set. + */ + virtual void setLocalScaling(const btVector3& scaling) + { + localScaling = scaling; + postUpdate(); + } + + virtual const btVector3& getLocalScaling() const + { + return localScaling; + } + + + virtual void setMargin(btScalar margin) + { + m_collisionMargin = margin; + int i = getNumChildShapes(); + while(i--) + { + btCollisionShape* child = getChildShape(i); + child->setMargin(margin); + } + + m_needs_update = true; + } + + + //! Subshape member functions + //!@{ + + //! Base method for determinig which kind of GIMPACT shape we get + virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() = 0; + + //! gets boxset + SIMD_FORCE_INLINE btGImpactBoxSet * getBoxSet() + { + return &m_box_set; + } + + //! Determines if this class has a hierarchy structure for sorting its primitives + SIMD_FORCE_INLINE bool hasBoxSet() const + { + if(m_box_set.getNodeCount() == 0) return false; + return true; + } + + //! Obtains the primitive manager + virtual const btPrimitiveManagerBase * getPrimitiveManager() const = 0; + + + //! Gets the number of children + virtual int getNumChildShapes() const = 0; + + //! if true, then its children must get transforms. + virtual bool childrenHasTransform() const = 0; + + //! Determines if this shape has triangles + virtual bool needsRetrieveTriangles() const = 0; + + //! Determines if this shape has tetrahedrons + virtual bool needsRetrieveTetrahedrons() const = 0; + + virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const = 0; + + virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const = 0; + + + + //! call when reading child shapes + virtual void lockChildShapes() const + { + } + + virtual void unlockChildShapes() const + { + } + + //! if this trimesh + SIMD_FORCE_INLINE void getPrimitiveTriangle(int index,btPrimitiveTriangle & triangle) const + { + getPrimitiveManager()->get_primitive_triangle(index,triangle); + } + + + //! Retrieves the bound from a child + /*! + */ + virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + btAABB child_aabb; + getPrimitiveManager()->get_primitive_box(child_index,child_aabb); + child_aabb.appy_transform(t); + aabbMin = child_aabb.m_min; + aabbMax = child_aabb.m_max; + } + + //! Gets the children + virtual btCollisionShape* getChildShape(int index) = 0; + + + //! Gets the child + virtual const btCollisionShape* getChildShape(int index) const = 0; + + //! Gets the children transform + virtual btTransform getChildTransform(int index) const = 0; + + //! Sets the children transform + /*! + \post You must call updateBound() for update the box set. + */ + virtual void setChildTransform(int index, const btTransform & transform) = 0; + + //!@} + + + //! virtual method for ray collision + virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const + { + } + + //! Function for retrieve triangles. + /*! + It gives the triangles in local space + */ + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const + { + } + + //!@} + +}; + + +//! btGImpactCompoundShape allows to handle multiple btCollisionShape objects at once +/*! +This class only can manage Convex subshapes +*/ +class btGImpactCompoundShape : public btGImpactShapeInterface +{ +public: + //! compound primitive manager + class CompoundPrimitiveManager:public btPrimitiveManagerBase + { + public: + btGImpactCompoundShape * m_compoundShape; + + + CompoundPrimitiveManager(const CompoundPrimitiveManager& compound) + { + m_compoundShape = compound.m_compoundShape; + } + + CompoundPrimitiveManager(btGImpactCompoundShape * compoundShape) + { + m_compoundShape = compoundShape; + } + + CompoundPrimitiveManager() + { + m_compoundShape = NULL; + } + + virtual bool is_trimesh() const + { + return false; + } + + virtual int get_primitive_count() const + { + return (int )m_compoundShape->getNumChildShapes(); + } + + virtual void get_primitive_box(int prim_index ,btAABB & primbox) const + { + btTransform prim_trans; + if(m_compoundShape->childrenHasTransform()) + { + prim_trans = m_compoundShape->getChildTransform(prim_index); + } + else + { + prim_trans.setIdentity(); + } + const btCollisionShape* shape = m_compoundShape->getChildShape(prim_index); + shape->getAabb(prim_trans,primbox.m_min,primbox.m_max); + } + + virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const + { + btAssert(0); + } + + }; + + + +protected: + CompoundPrimitiveManager m_primitive_manager; + btAlignedObjectArray m_childTransforms; + btAlignedObjectArray m_childShapes; + + +public: + + btGImpactCompoundShape(bool children_has_transform = true) + { + m_primitive_manager.m_compoundShape = this; + m_box_set.setPrimitiveManager(&m_primitive_manager); + } + + virtual ~btGImpactCompoundShape() + { + } + + + //! if true, then its children must get transforms. + virtual bool childrenHasTransform() const + { + if(m_childTransforms.size()==0) return false; + return true; + } + + + //! Obtains the primitive manager + virtual const btPrimitiveManagerBase * getPrimitiveManager() const + { + return &m_primitive_manager; + } + + //! Obtains the compopund primitive manager + SIMD_FORCE_INLINE CompoundPrimitiveManager * getCompoundPrimitiveManager() + { + return &m_primitive_manager; + } + + //! Gets the number of children + virtual int getNumChildShapes() const + { + return m_childShapes.size(); + } + + + //! Use this method for adding children. Only Convex shapes are allowed. + void addChildShape(const btTransform& localTransform,btCollisionShape* shape) + { + btAssert(shape->isConvex()); + m_childTransforms.push_back(localTransform); + m_childShapes.push_back(shape); + } + + //! Use this method for adding children. Only Convex shapes are allowed. + void addChildShape(btCollisionShape* shape) + { + btAssert(shape->isConvex()); + m_childShapes.push_back(shape); + } + + //! Gets the children + virtual btCollisionShape* getChildShape(int index) + { + return m_childShapes[index]; + } + + //! Gets the children + virtual const btCollisionShape* getChildShape(int index) const + { + return m_childShapes[index]; + } + + //! Retrieves the bound from a child + /*! + */ + virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + + if(childrenHasTransform()) + { + m_childShapes[child_index]->getAabb(t*m_childTransforms[child_index],aabbMin,aabbMax); + } + else + { + m_childShapes[child_index]->getAabb(t,aabbMin,aabbMax); + } + } + + + //! Gets the children transform + virtual btTransform getChildTransform(int index) const + { + btAssert(m_childTransforms.size() == m_childShapes.size()); + return m_childTransforms[index]; + } + + //! Sets the children transform + /*! + \post You must call updateBound() for update the box set. + */ + virtual void setChildTransform(int index, const btTransform & transform) + { + btAssert(m_childTransforms.size() == m_childShapes.size()); + m_childTransforms[index] = transform; + postUpdate(); + } + + //! Determines if this shape has triangles + virtual bool needsRetrieveTriangles() const + { + return false; + } + + //! Determines if this shape has tetrahedrons + virtual bool needsRetrieveTetrahedrons() const + { + return false; + } + + + virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const + { + btAssert(0); + } + + virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const + { + btAssert(0); + } + + + //! Calculates the exact inertia tensor for this shape + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual const char* getName()const + { + return "GImpactCompound"; + } + + virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() + { + return CONST_GIMPACT_COMPOUND_SHAPE; + } + +}; + + + +//! This class manages a sub part of a mesh supplied by the btStridingMeshInterface interface. +/*! +- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShapePart, then you must call updateBound() after creating the mesh +- When making operations with this shape, you must call lock before accessing to the trimesh primitives, and then call unlock +- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices. + +*/ +class btGImpactMeshShapePart : public btGImpactShapeInterface +{ +public: + //! Trimesh primitive manager + /*! + Manages the info from btStridingMeshInterface object and controls the Lock/Unlock mechanism + */ + class TrimeshPrimitiveManager:public btPrimitiveManagerBase + { + public: + btScalar m_margin; + btStridingMeshInterface * m_meshInterface; + btVector3 m_scale; + int m_part; + int m_lock_count; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + + TrimeshPrimitiveManager() + { + m_meshInterface = NULL; + m_part = 0; + m_margin = 0.01f; + m_scale = btVector3(1.f,1.f,1.f); + m_lock_count = 0; + vertexbase = 0; + numverts = 0; + stride = 0; + indexbase = 0; + indexstride = 0; + numfaces = 0; + } + + TrimeshPrimitiveManager(const TrimeshPrimitiveManager & manager) + { + m_meshInterface = manager.m_meshInterface; + m_part = manager.m_part; + m_margin = manager.m_margin; + m_scale = manager.m_scale; + m_lock_count = 0; + vertexbase = 0; + numverts = 0; + stride = 0; + indexbase = 0; + indexstride = 0; + numfaces = 0; + + } + + TrimeshPrimitiveManager( + btStridingMeshInterface * meshInterface, int part) + { + m_meshInterface = meshInterface; + m_part = part; + m_scale = m_meshInterface->getScaling(); + m_margin = 0.1f; + m_lock_count = 0; + vertexbase = 0; + numverts = 0; + stride = 0; + indexbase = 0; + indexstride = 0; + numfaces = 0; + + } + + + void lock() + { + if(m_lock_count>0) + { + m_lock_count++; + return; + } + m_meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase,numverts, + type, stride,&indexbase, indexstride, numfaces,indicestype,m_part); + + m_lock_count = 1; + } + + void unlock() + { + if(m_lock_count == 0) return; + if(m_lock_count>1) + { + --m_lock_count; + return; + } + m_meshInterface->unLockReadOnlyVertexBase(m_part); + vertexbase = NULL; + m_lock_count = 0; + } + + virtual bool is_trimesh() const + { + return true; + } + + virtual int get_primitive_count() const + { + return (int )numfaces; + } + + SIMD_FORCE_INLINE int get_vertex_count() const + { + return (int )numverts; + } + + SIMD_FORCE_INLINE void get_indices(int face_index,int &i0,int &i1,int &i2) const + { + if(indicestype == PHY_SHORT) + { + short * s_indices = (short *)(indexbase + face_index*indexstride); + i0 = s_indices[0]; + i1 = s_indices[1]; + i2 = s_indices[2]; + } + else + { + int * i_indices = (int *)(indexbase + face_index*indexstride); + i0 = i_indices[0]; + i1 = i_indices[1]; + i2 = i_indices[2]; + } + } + + SIMD_FORCE_INLINE void get_vertex(int vertex_index, btVector3 & vertex) const + { + if(type == PHY_DOUBLE) + { + double * dvertices = (double *)(vertexbase + vertex_index*stride); + vertex[0] = btScalar(dvertices[0]*m_scale[0]); + vertex[1] = btScalar(dvertices[1]*m_scale[1]); + vertex[2] = btScalar(dvertices[2]*m_scale[2]); + } + else + { + float * svertices = (float *)(vertexbase + vertex_index*stride); + vertex[0] = svertices[0]*m_scale[0]; + vertex[1] = svertices[1]*m_scale[1]; + vertex[2] = svertices[2]*m_scale[2]; + } + } + + virtual void get_primitive_box(int prim_index ,btAABB & primbox) const + { + btPrimitiveTriangle triangle; + get_primitive_triangle(prim_index,triangle); + primbox.calc_from_triangle_margin( + triangle.m_vertices[0], + triangle.m_vertices[1],triangle.m_vertices[2],triangle.m_margin); + } + + virtual void get_primitive_triangle(int prim_index,btPrimitiveTriangle & triangle) const + { + int indices[3]; + get_indices(prim_index,indices[0],indices[1],indices[2]); + get_vertex(indices[0],triangle.m_vertices[0]); + get_vertex(indices[1],triangle.m_vertices[1]); + get_vertex(indices[2],triangle.m_vertices[2]); + triangle.m_margin = m_margin; + } + + SIMD_FORCE_INLINE void get_bullet_triangle(int prim_index,btTriangleShapeEx & triangle) const + { + int indices[3]; + get_indices(prim_index,indices[0],indices[1],indices[2]); + get_vertex(indices[0],triangle.m_vertices1[0]); + get_vertex(indices[1],triangle.m_vertices1[1]); + get_vertex(indices[2],triangle.m_vertices1[2]); + triangle.setMargin(m_margin); + } + + }; + + +protected: + TrimeshPrimitiveManager m_primitive_manager; +public: + + btGImpactMeshShapePart() + { + m_box_set.setPrimitiveManager(&m_primitive_manager); + } + + + btGImpactMeshShapePart(btStridingMeshInterface * meshInterface, int part) + { + m_primitive_manager.m_meshInterface = meshInterface; + m_primitive_manager.m_part = part; + m_box_set.setPrimitiveManager(&m_primitive_manager); + } + + virtual ~btGImpactMeshShapePart() + { + } + + //! if true, then its children must get transforms. + virtual bool childrenHasTransform() const + { + return false; + } + + + //! call when reading child shapes + virtual void lockChildShapes() const + { + void * dummy = (void*)(m_box_set.getPrimitiveManager()); + TrimeshPrimitiveManager * dummymanager = static_cast(dummy); + dummymanager->lock(); + } + + virtual void unlockChildShapes() const + { + void * dummy = (void*)(m_box_set.getPrimitiveManager()); + TrimeshPrimitiveManager * dummymanager = static_cast(dummy); + dummymanager->unlock(); + } + + //! Gets the number of children + virtual int getNumChildShapes() const + { + return m_primitive_manager.get_primitive_count(); + } + + + //! Gets the children + virtual btCollisionShape* getChildShape(int index) + { + btAssert(0); + return NULL; + } + + + + //! Gets the child + virtual const btCollisionShape* getChildShape(int index) const + { + btAssert(0); + return NULL; + } + + //! Gets the children transform + virtual btTransform getChildTransform(int index) const + { + btAssert(0); + return btTransform(); + } + + //! Sets the children transform + /*! + \post You must call updateBound() for update the box set. + */ + virtual void setChildTransform(int index, const btTransform & transform) + { + btAssert(0); + } + + + //! Obtains the primitive manager + virtual const btPrimitiveManagerBase * getPrimitiveManager() const + { + return &m_primitive_manager; + } + + SIMD_FORCE_INLINE TrimeshPrimitiveManager * getTrimeshPrimitiveManager() + { + return &m_primitive_manager; + } + + + + + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + + + + virtual const char* getName()const + { + return "GImpactMeshShapePart"; + } + + virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() + { + return CONST_GIMPACT_TRIMESH_SHAPE_PART; + } + + //! Determines if this shape has triangles + virtual bool needsRetrieveTriangles() const + { + return true; + } + + //! Determines if this shape has tetrahedrons + virtual bool needsRetrieveTetrahedrons() const + { + return false; + } + + virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const + { + m_primitive_manager.get_bullet_triangle(prim_index,triangle); + } + + virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const + { + btAssert(0); + } + + + + SIMD_FORCE_INLINE int getVertexCount() const + { + return m_primitive_manager.get_vertex_count(); + } + + SIMD_FORCE_INLINE void getVertex(int vertex_index, btVector3 & vertex) const + { + m_primitive_manager.get_vertex(vertex_index,vertex); + } + + SIMD_FORCE_INLINE void setMargin(btScalar margin) + { + m_primitive_manager.m_margin = margin; + postUpdate(); + } + + SIMD_FORCE_INLINE btScalar getMargin() const + { + return m_primitive_manager.m_margin; + } + + virtual void setLocalScaling(const btVector3& scaling) + { + m_primitive_manager.m_scale = scaling; + postUpdate(); + } + + virtual const btVector3& getLocalScaling() const + { + return m_primitive_manager.m_scale; + } + + SIMD_FORCE_INLINE int getPart() const + { + return (int)m_primitive_manager.m_part; + } + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; +}; + + +//! This class manages a mesh supplied by the btStridingMeshInterface interface. +/*! +Set of btGImpactMeshShapePart parts +- Simply create this shape by passing the btStridingMeshInterface to the constructor btGImpactMeshShape, then you must call updateBound() after creating the mesh + +- You can handle deformable meshes with this shape, by calling postUpdate() every time when changing the mesh vertices. + +*/ +class btGImpactMeshShape : public btGImpactShapeInterface +{ +protected: + btAlignedObjectArray m_mesh_parts; + void buildMeshParts(btStridingMeshInterface * meshInterface) + { + for (int i=0;igetNumSubParts() ;++i ) + { + btGImpactMeshShapePart * newpart = new btGImpactMeshShapePart(meshInterface,i); + m_mesh_parts.push_back(newpart); + } + } + + //! use this function for perfofm refit in bounding boxes + virtual void calcLocalAABB() + { + m_localAABB.invalidate(); + int i = m_mesh_parts.size(); + while(i--) + { + m_mesh_parts[i]->updateBound(); + m_localAABB.merge(m_mesh_parts[i]->getLocalBox()); + } + } + +public: + btGImpactMeshShape(btStridingMeshInterface * meshInterface) + { + buildMeshParts(meshInterface); + } + + virtual ~btGImpactMeshShape() + { + int i = m_mesh_parts.size(); + while(i--) + { + btGImpactMeshShapePart * part = m_mesh_parts[i]; + delete part; + } + m_mesh_parts.clear(); + } + + + + int getMeshPartCount() const + { + return m_mesh_parts.size(); + } + + btGImpactMeshShapePart * getMeshPart(int index) + { + return m_mesh_parts[index]; + } + + + + const btGImpactMeshShapePart * getMeshPart(int index) const + { + return m_mesh_parts[index]; + } + + + virtual void setLocalScaling(const btVector3& scaling) + { + localScaling = scaling; + + int i = m_mesh_parts.size(); + while(i--) + { + btGImpactMeshShapePart * part = m_mesh_parts[i]; + part->setLocalScaling(scaling); + } + + m_needs_update = true; + } + + virtual void setMargin(btScalar margin) + { + m_collisionMargin = margin; + + int i = m_mesh_parts.size(); + while(i--) + { + btGImpactMeshShapePart * part = m_mesh_parts[i]; + part->setMargin(margin); + } + + m_needs_update = true; + } + + //! Tells to this object that is needed to refit all the meshes + virtual void postUpdate() + { + int i = m_mesh_parts.size(); + while(i--) + { + btGImpactMeshShapePart * part = m_mesh_parts[i]; + part->postUpdate(); + } + + m_needs_update = true; + } + + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + + //! Obtains the primitive manager + virtual const btPrimitiveManagerBase * getPrimitiveManager() const + { + btAssert(0); + return NULL; + } + + + //! Gets the number of children + virtual int getNumChildShapes() const + { + btAssert(0); + return 0; + } + + + //! if true, then its children must get transforms. + virtual bool childrenHasTransform() const + { + btAssert(0); + return false; + } + + //! Determines if this shape has triangles + virtual bool needsRetrieveTriangles() const + { + btAssert(0); + return false; + } + + //! Determines if this shape has tetrahedrons + virtual bool needsRetrieveTetrahedrons() const + { + btAssert(0); + return false; + } + + virtual void getBulletTriangle(int prim_index,btTriangleShapeEx & triangle) const + { + btAssert(0); + } + + virtual void getBulletTetrahedron(int prim_index,btTetrahedronShapeEx & tetrahedron) const + { + btAssert(0); + } + + //! call when reading child shapes + virtual void lockChildShapes() + { + btAssert(0); + } + + virtual void unlockChildShapes() + { + btAssert(0); + } + + + + + //! Retrieves the bound from a child + /*! + */ + virtual void getChildAabb(int child_index,const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const + { + btAssert(0); + } + + //! Gets the children + virtual btCollisionShape* getChildShape(int index) + { + btAssert(0); + return NULL; + } + + + //! Gets the child + virtual const btCollisionShape* getChildShape(int index) const + { + btAssert(0); + return NULL; + } + + //! Gets the children transform + virtual btTransform getChildTransform(int index) const + { + btAssert(0); + return btTransform(); + } + + //! Sets the children transform + /*! + \post You must call updateBound() for update the box set. + */ + virtual void setChildTransform(int index, const btTransform & transform) + { + btAssert(0); + } + + + virtual eGIMPACT_SHAPE_TYPE getGImpactShapeType() + { + return CONST_GIMPACT_TRIMESH_SHAPE; + } + + + virtual const char* getName()const + { + return "GImpactMesh"; + } + + virtual void rayTest(const btVector3& rayFrom, const btVector3& rayTo, btCollisionWorld::RayResultCallback& resultCallback) const; + + //! Function for retrieve triangles. + /*! + It gives the triangles in local space + */ + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; +}; + + +#endif //GIMPACT_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp b/extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp new file mode 100644 index 00000000000..a1e46e65575 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGenericPoolAllocator.cpp @@ -0,0 +1,283 @@ +/*! \file btGenericPoolAllocator.cpp +\author Francisco León Nájera. email projectileman@yahoo.com + +General purpose allocator class +*/ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btGenericPoolAllocator.h" + + + +/// *************** btGenericMemoryPool ******************/////////// + +size_t btGenericMemoryPool::allocate_from_free_nodes(size_t num_elements) +{ + size_t ptr = BT_UINT_MAX; + + if(m_free_nodes_count == 0) return BT_UINT_MAX; + // find an avaliable free node with the correct size + size_t revindex = m_free_nodes_count; + + while(revindex-- && ptr == BT_UINT_MAX) + { + if(m_allocated_sizes[m_free_nodes[revindex]]>=num_elements) + { + ptr = revindex; + } + } + if(ptr == BT_UINT_MAX) return BT_UINT_MAX; // not found + + + revindex = ptr; + ptr = m_free_nodes[revindex]; + // post: ptr contains the node index, and revindex the index in m_free_nodes + + size_t finalsize = m_allocated_sizes[ptr]; + finalsize -= num_elements; + + m_allocated_sizes[ptr] = num_elements; + + // post: finalsize>=0, m_allocated_sizes[ptr] has the requested size + + if(finalsize>0) // preserve free node, there are some free memory + { + m_free_nodes[revindex] = ptr + num_elements; + m_allocated_sizes[ptr + num_elements] = finalsize; + } + else // delete free node + { + // swap with end + m_free_nodes[revindex] = m_free_nodes[m_free_nodes_count-1]; + m_free_nodes_count--; + } + + return ptr; +} + +size_t btGenericMemoryPool::allocate_from_pool(size_t num_elements) +{ + if(m_allocated_count+num_elements>m_max_element_count) return BT_UINT_MAX; + + size_t ptr = m_allocated_count; + + m_allocated_sizes[m_allocated_count] = num_elements; + m_allocated_count+=num_elements; + + return ptr; +} + + +void btGenericMemoryPool::init_pool(size_t element_size, size_t element_count) +{ + m_allocated_count = 0; + m_free_nodes_count = 0; + + m_element_size = element_size; + m_max_element_count = element_count; + + + + + m_pool = (unsigned char *) btAlignedAlloc(m_element_size*m_max_element_count,16); + m_free_nodes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16); + m_allocated_sizes = (size_t *) btAlignedAlloc(sizeof(size_t)*m_max_element_count,16); + + for (size_t i = 0;i< m_max_element_count;i++ ) + { + m_allocated_sizes[i] = 0; + } +} + +void btGenericMemoryPool::end_pool() +{ + btAlignedFree(m_pool); + btAlignedFree(m_free_nodes); + btAlignedFree(m_allocated_sizes); + m_allocated_count = 0; + m_free_nodes_count = 0; +} + + +//! Allocates memory in pool +/*! +\param size_bytes size in bytes of the buffer +*/ +void * btGenericMemoryPool::allocate(size_t size_bytes) +{ + + size_t module = size_bytes%m_element_size; + size_t element_count = size_bytes/m_element_size; + if(module>0) element_count++; + + size_t alloc_pos = allocate_from_free_nodes(element_count); + // a free node is found + if(alloc_pos != BT_UINT_MAX) + { + return get_element_data(alloc_pos); + } + // allocate directly on pool + alloc_pos = allocate_from_pool(element_count); + + if(alloc_pos == BT_UINT_MAX) return NULL; // not space + return get_element_data(alloc_pos); +} + +bool btGenericMemoryPool::freeMemory(void * pointer) +{ + unsigned char * pointer_pos = (unsigned char *)pointer; + unsigned char * pool_pos = (unsigned char *)m_pool; + // calc offset + if(pointer_pos=get_pool_capacity()) return false;// far away + + // find free position + m_free_nodes[m_free_nodes_count] = offset/m_element_size; + m_free_nodes_count++; + return true; +} + + +/// *******************! btGenericPoolAllocator *******************!/// + + +btGenericPoolAllocator::~btGenericPoolAllocator() +{ + // destroy pools + size_t i; + for (i=0;iend_pool(); + btAlignedFree(m_pools[i]); + } +} + + +// creates a pool +btGenericMemoryPool * btGenericPoolAllocator::push_new_pool() +{ + if(m_pool_count >= BT_DEFAULT_MAX_POOLS) return NULL; + + btGenericMemoryPool * newptr = (btGenericMemoryPool *)btAlignedAlloc(sizeof(btGenericMemoryPool),16); + + m_pools[m_pool_count] = newptr; + + m_pools[m_pool_count]->init_pool(m_pool_element_size,m_pool_element_count); + + m_pool_count++; + return newptr; +} + +void * btGenericPoolAllocator::failback_alloc(size_t size_bytes) +{ + + btGenericMemoryPool * pool = NULL; + + + if(size_bytes<=get_pool_capacity()) + { + pool = push_new_pool(); + } + + if(pool==NULL) // failback + { + return btAlignedAlloc(size_bytes,16); + } + + return pool->allocate(size_bytes); +} + +bool btGenericPoolAllocator::failback_free(void * pointer) +{ + btAlignedFree(pointer); + return true; +} + + +//! Allocates memory in pool +/*! +\param size_bytes size in bytes of the buffer +*/ +void * btGenericPoolAllocator::allocate(size_t size_bytes) +{ + void * ptr = NULL; + + size_t i = 0; + while(iallocate(size_bytes); + ++i; + } + + if(ptr) return ptr; + + return failback_alloc(size_bytes); +} + +bool btGenericPoolAllocator::freeMemory(void * pointer) +{ + bool result = false; + + size_t i = 0; + while(ifreeMemory(pointer); + ++i; + } + + if(result) return true; + + return failback_free(pointer); +} + +/// ************** STANDARD ALLOCATOR ***************************/// + + +#define BT_DEFAULT_POOL_SIZE 32768 +#define BT_DEFAULT_POOL_ELEMENT_SIZE 8 + +// main allocator +class BT_STANDARD_ALLOCATOR: public btGenericPoolAllocator +{ +public: + BT_STANDARD_ALLOCATOR():btGenericPoolAllocator(BT_DEFAULT_POOL_ELEMENT_SIZE,BT_DEFAULT_POOL_SIZE) + { + } +}; + +// global allocator +BT_STANDARD_ALLOCATOR g_main_allocator; + + +void * btPoolAlloc(size_t size) +{ + return g_main_allocator.allocate(size); +} + +void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize) +{ + void * newptr = btPoolAlloc(newsize); + size_t copysize = oldsize +#include +#include +#include "LinearMath/btAlignedAllocator.h" + +#define BT_UINT_MAX UINT_MAX +#define BT_DEFAULT_MAX_POOLS 16 + + +//! Generic Pool class +class btGenericMemoryPool +{ +public: + unsigned char * m_pool; //[m_element_size*m_max_element_count]; + size_t * m_free_nodes; //[m_max_element_count];//! free nodes + size_t * m_allocated_sizes;//[m_max_element_count];//! Number of elements allocated per node + size_t m_allocated_count; + size_t m_free_nodes_count; +protected: + size_t m_element_size; + size_t m_max_element_count; + + size_t allocate_from_free_nodes(size_t num_elements); + size_t allocate_from_pool(size_t num_elements); + +public: + + void init_pool(size_t element_size, size_t element_count); + + void end_pool(); + + + btGenericMemoryPool(size_t element_size, size_t element_count) + { + init_pool(element_size, element_count); + } + + ~btGenericMemoryPool() + { + end_pool(); + } + + + inline size_t get_pool_capacity() + { + return m_element_size*m_max_element_count; + } + + inline size_t gem_element_size() + { + return m_element_size; + } + + inline size_t get_max_element_count() + { + return m_max_element_count; + } + + inline size_t get_allocated_count() + { + return m_allocated_count; + } + + inline size_t get_free_positions_count() + { + return m_free_nodes_count; + } + + inline void * get_element_data(size_t element_index) + { + return &m_pool[element_index*m_element_size]; + } + + //! Allocates memory in pool + /*! + \param size_bytes size in bytes of the buffer + */ + void * allocate(size_t size_bytes); + + bool freeMemory(void * pointer); +}; + + + + +//! Generic Allocator with pools +/*! +General purpose Allocator which can create Memory Pools dynamiacally as needed. +*/ +class btGenericPoolAllocator +{ +protected: + size_t m_pool_element_size; + size_t m_pool_element_count; +public: + btGenericMemoryPool * m_pools[BT_DEFAULT_MAX_POOLS]; + size_t m_pool_count; + + + inline size_t get_pool_capacity() + { + return m_pool_element_size*m_pool_element_count; + } + + +protected: + // creates a pool + btGenericMemoryPool * push_new_pool(); + + void * failback_alloc(size_t size_bytes); + + bool failback_free(void * pointer); +public: + + btGenericPoolAllocator(size_t pool_element_size, size_t pool_element_count) + { + m_pool_count = 0; + m_pool_element_size = pool_element_size; + m_pool_element_count = pool_element_count; + } + + virtual ~btGenericPoolAllocator(); + + //! Allocates memory in pool + /*! + \param size_bytes size in bytes of the buffer + */ + void * allocate(size_t size_bytes); + + bool freeMemory(void * pointer); +}; + + + +/*! \defgroup POOL_MEMORY_FUNCTIONS +standar managed Memory functions. Memory pools are used. +*/ +//! @{ +void * btPoolAlloc(size_t size); +void * btPoolRealloc(void *ptr, size_t oldsize, size_t newsize); +void btPoolFree(void *ptr); +//! @} + + +#endif diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btGeometryOperations.h b/extern/bullet2/src/BulletCollision/Gimpact/btGeometryOperations.h new file mode 100644 index 00000000000..72ab00e6cb4 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/btGeometryOperations.h @@ -0,0 +1,216 @@ +#ifndef BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED +#define BT_BASIC_GEOMETRY_OPERATIONS_H_INCLUDED + +/*! \file btGeometryOperations.h +*\author Francisco León Nájera + +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "btBoxCollision.h" + + + +/*! \defgroup GEOMETRIC_OPERATIONS +*/ +//! @{ + + +#define PLANEDIREPSILON 0.0000001f +#define PARALELENORMALS 0.000001f + + +#define BT_CLAMP(number,minval,maxval) (numbermaxval?maxval:number)) + +/// Calc a plane from a triangle edge an a normal. plane is a vec4f +SIMD_FORCE_INLINE void bt_edge_plane(const btVector3 & e1,const btVector3 & e2, const btVector3 & normal,btVector4 & plane) +{ + btVector3 planenormal = (e2-e1).cross(normal); + planenormal.normalize(); + plane.setValue(planenormal[0],planenormal[1],planenormal[2],e2.dot(planenormal)); +} + + + +//***************** SEGMENT and LINE FUNCTIONS **********************************/// + +/*! Finds the closest point(cp) to (v) on a segment (e1,e2) + */ +SIMD_FORCE_INLINE void bt_closest_point_on_segment( + btVector3 & cp, const btVector3 & v, + const btVector3 &e1,const btVector3 &e2) +{ + btVector3 n = e2-e1; + cp = v - e1; + btScalar _scalar = cp.dot(n)/n.dot(n); + if(_scalar <0.0f) + { + cp = e1; + } + else if(_scalar >1.0f) + { + cp = e2; + } + else + { + cp = _scalar*n + e1; + } +} + + +//! line plane collision +/*! +*\return + -0 if the ray never intersects + -1 if the ray collides in front + -2 if the ray collides in back +*/ + +SIMD_FORCE_INLINE int bt_line_plane_collision( + const btVector4 & plane, + const btVector3 & vDir, + const btVector3 & vPoint, + btVector3 & pout, + btScalar &tparam, + btScalar tmin, btScalar tmax) +{ + + btScalar _dotdir = vDir.dot(plane); + + if(btFabs(_dotdir)tmax) + { + returnvalue = 0; + tparam = tmax; + } + pout = tparam*vDir + vPoint; + return returnvalue; +} + + +//! Find closest points on segments +SIMD_FORCE_INLINE void bt_segment_collision( + const btVector3 & vA1, + const btVector3 & vA2, + const btVector3 & vB1, + const btVector3 & vB2, + btVector3 & vPointA, + btVector3 & vPointB) +{ + btVector3 AD = vA2 - vA1; + btVector3 BD = vB2 - vB1; + btVector3 N = AD.cross(BD); + btScalar tp = N.length2(); + + btVector4 _M;//plane + + if(tp_M[1]) + { + invert_b_order = true; + BT_SWAP_NUMBERS(_M[0],_M[1]); + } + _M[2] = vA1.dot(AD); + _M[3] = vA2.dot(AD); + //mid points + N[0] = (_M[0]+_M[1])*0.5f; + N[1] = (_M[2]+_M[3])*0.5f; + + if(N[0]=0.0f) + { + if (_dist>m_penetration_depth) + { + m_penetration_depth = _dist; + point_indices[0] = _k; + m_point_count=1; + } + else if ((_dist+SIMD_EPSILON)>=m_penetration_depth) + { + point_indices[m_point_count] = _k; + m_point_count++; + } + } + } + + for ( _k=0;_k0.0f&&dis1>0.0f&&dis2>0.0f) return false; + + // classify points on this triangle + dis0 = bt_distance_point_plane(other.m_plane,m_vertices[0]) - total_margin; + + dis1 = bt_distance_point_plane(other.m_plane,m_vertices[1]) - total_margin; + + dis2 = bt_distance_point_plane(other.m_plane,m_vertices[2]) - total_margin; + + if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false; + + return true; +} + +int btPrimitiveTriangle::clip_triangle(btPrimitiveTriangle & other, btVector3 * clipped_points ) +{ + // edge 0 + + btVector3 temp_points[MAX_TRI_CLIPPING]; + + + btVector4 edgeplane; + + get_edge_plane(0,edgeplane); + + + int clipped_count = bt_plane_clip_triangle( + edgeplane,other.m_vertices[0],other.m_vertices[1],other.m_vertices[2],temp_points); + + if (clipped_count == 0) return 0; + + btVector3 temp_points1[MAX_TRI_CLIPPING]; + + + // edge 1 + get_edge_plane(1,edgeplane); + + + clipped_count = bt_plane_clip_polygon(edgeplane,temp_points,clipped_count,temp_points1); + + if (clipped_count == 0) return 0; + + // edge 2 + get_edge_plane(2,edgeplane); + + clipped_count = bt_plane_clip_polygon( + edgeplane,temp_points1,clipped_count,clipped_points); + + return clipped_count; +} + +bool btPrimitiveTriangle::find_triangle_collision_clip_method(btPrimitiveTriangle & other, BT_TRIANGLE_CONTACT & contacts) +{ + btScalar margin = m_margin + other.m_margin; + + btVector3 clipped_points[MAX_TRI_CLIPPING]; + int clipped_count; + //create planes + // plane v vs U points + + BT_TRIANGLE_CONTACT contacts1; + + contacts1.m_separating_normal = m_plane; + + + clipped_count = clip_triangle(other,clipped_points); + + if (clipped_count == 0 ) + { + return false;//Reject + } + + //find most deep interval face1 + contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count); + if (contacts1.m_point_count == 0) return false; // too far + //Normal pointing to this triangle + contacts1.m_separating_normal *= -1.f; + + + //Clip tri1 by tri2 edges + BT_TRIANGLE_CONTACT contacts2; + contacts2.m_separating_normal = other.m_plane; + + clipped_count = other.clip_triangle(*this,clipped_points); + + if (clipped_count == 0 ) + { + return false;//Reject + } + + //find most deep interval face1 + contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count); + if (contacts2.m_point_count == 0) return false; // too far + + + + + ////check most dir for contacts + if (contacts2.m_penetration_depth0.0f&&dis1>0.0f&&dis2>0.0f) return false; + + // classify points on this triangle + dis0 = bt_distance_point_plane(plane1,m_vertices1[0]) - total_margin; + + dis1 = bt_distance_point_plane(plane1,m_vertices1[1]) - total_margin; + + dis2 = bt_distance_point_plane(plane1,m_vertices1[2]) - total_margin; + + if (dis0>0.0f&&dis1>0.0f&&dis2>0.0f) return false; + + return true; +} + + diff --git a/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.h b/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.h new file mode 100644 index 00000000000..c5c737cf2be --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/btTriangleShapeEx.h @@ -0,0 +1,180 @@ +/*! \file btGImpactShape.h +\author Francisco León Nájera +*/ +/* +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2007 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + + +#ifndef TRIANGLE_SHAPE_EX_H +#define TRIANGLE_SHAPE_EX_H + +#include "BulletCollision/CollisionShapes/btCollisionShape.h" +#include "BulletCollision/CollisionShapes/btTriangleShape.h" +#include "btBoxCollision.h" +#include "btClipPolygon.h" +#include "btGeometryOperations.h" + + +#define MAX_TRI_CLIPPING 16 + +//! Structure for collision +struct BT_TRIANGLE_CONTACT +{ + btScalar m_penetration_depth; + int m_point_count; + btVector4 m_separating_normal; + btVector3 m_points[MAX_TRI_CLIPPING]; + + SIMD_FORCE_INLINE void copy_from(const BT_TRIANGLE_CONTACT& other) + { + m_penetration_depth = other.m_penetration_depth; + m_separating_normal = other.m_separating_normal; + m_point_count = other.m_point_count; + int i = m_point_count; + while(i--) + { + m_points[i] = other.m_points[i]; + } + } + + BT_TRIANGLE_CONTACT() + { + } + + BT_TRIANGLE_CONTACT(const BT_TRIANGLE_CONTACT& other) + { + copy_from(other); + } + + //! classify points that are closer + void merge_points(const btVector4 & plane, + btScalar margin, const btVector3 * points, int point_count); + +}; + + + +class btPrimitiveTriangle +{ +public: + btVector3 m_vertices[3]; + btVector4 m_plane; + btScalar m_margin; + btScalar m_dummy; + btPrimitiveTriangle():m_margin(0.01f) + { + + } + + + SIMD_FORCE_INLINE void buildTriPlane() + { + btVector3 normal = (m_vertices[1]-m_vertices[0]).cross(m_vertices[2]-m_vertices[0]); + normal.normalize(); + m_plane.setValue(normal[0],normal[1],normal[2],m_vertices[0].dot(normal)); + } + + //! Test if triangles could collide + bool overlap_test_conservative(const btPrimitiveTriangle& other); + + //! Calcs the plane which is paralele to the edge and perpendicular to the triangle plane + /*! + \pre this triangle must have its plane calculated. + */ + SIMD_FORCE_INLINE void get_edge_plane(int edge_index, btVector4 &plane) const + { + const btVector3 & e0 = m_vertices[edge_index]; + const btVector3 & e1 = m_vertices[(edge_index+1)%3]; + bt_edge_plane(e0,e1,m_plane,plane); + } + + void applyTransform(const btTransform& t) + { + m_vertices[0] = t(m_vertices[0]); + m_vertices[1] = t(m_vertices[1]); + m_vertices[2] = t(m_vertices[2]); + } + + //! Clips the triangle against this + /*! + \pre clipped_points must have MAX_TRI_CLIPPING size, and this triangle must have its plane calculated. + \return the number of clipped points + */ + int clip_triangle(btPrimitiveTriangle & other, btVector3 * clipped_points ); + + //! Find collision using the clipping method + /*! + \pre this triangle and other must have their triangles calculated + */ + bool find_triangle_collision_clip_method(btPrimitiveTriangle & other, BT_TRIANGLE_CONTACT & contacts); +}; + + + +//! Helper class for colliding Bullet Triangle Shapes +/*! +This class implements a better getAabb method than the previous btTriangleShape class +*/ +class btTriangleShapeEx: public btTriangleShape +{ +public: + + btTriangleShapeEx():btTriangleShape(btVector3(0,0,0),btVector3(0,0,0),btVector3(0,0,0)) + { + } + + btTriangleShapeEx(const btVector3& p0,const btVector3& p1,const btVector3& p2): btTriangleShape(p0,p1,p2) + { + } + + btTriangleShapeEx(const btTriangleShapeEx & other): btTriangleShape(other.m_vertices1[0],other.m_vertices1[1],other.m_vertices1[2]) + { + } + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax)const + { + btVector3 tv0 = t(m_vertices1[0]); + btVector3 tv1 = t(m_vertices1[1]); + btVector3 tv2 = t(m_vertices1[2]); + + btAABB trianglebox(tv0,tv1,tv2,m_collisionMargin); + aabbMin = trianglebox.m_min; + aabbMax = trianglebox.m_max; + } + + void applyTransform(const btTransform& t) + { + m_vertices1[0] = t(m_vertices1[0]); + m_vertices1[1] = t(m_vertices1[1]); + m_vertices1[2] = t(m_vertices1[2]); + } + + SIMD_FORCE_INLINE void buildTriPlane(btVector4 & plane) const + { + btVector3 normal = (m_vertices1[1]-m_vertices1[0]).cross(m_vertices1[2]-m_vertices1[0]); + normal.normalize(); + plane.setValue(normal[0],normal[1],normal[2],m_vertices1[0].dot(normal)); + } + + bool overlap_test_conservative(const btTriangleShapeEx& other); +}; + + +#endif //TRIANGLE_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_array.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_array.h new file mode 100644 index 00000000000..80c35f71139 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_array.h @@ -0,0 +1,332 @@ +#ifndef GIM_ARRAY_H_INCLUDED +#define GIM_ARRAY_H_INCLUDED +/*! \file gim_array.h +\author Francisco León Nájera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "gim_memory.h" + +/*! \addtogroup CONTAINERS +\brief +Abstract class for template containers +*/ +//! @{ + +#define GIM_ARRAY_GROW_INCREMENT 2 +#define GIM_ARRAY_GROW_FACTOR 2 + +//! Very simple array container with fast access and simd memory +template +class gim_array +{ +public: +//! properties +//!@{ + T *m_data; + GUINT m_size; + GUINT m_allocated_size; +//!@} +//! protected operations +//!@{ + + inline void destroyData() + { + m_allocated_size = 0; + if(m_data==NULL) return; + gim_free(m_data); + m_data = NULL; + } + + inline bool resizeData(GUINT newsize) + { + if(newsize==0) + { + destroyData(); + return true; + } + + if(m_size>0) + { + m_data = (T*)gim_realloc(m_data,m_size*sizeof(T),newsize*sizeof(T)); + } + else + { + m_data = (T*)gim_alloc(newsize*sizeof(T)); + } + m_allocated_size = newsize; + return true; + } + + inline bool growingCheck() + { + if(m_allocated_size<=m_size) + { + GUINT requestsize = m_size; + m_size = m_allocated_size; + if(resizeData((requestsize+GIM_ARRAY_GROW_INCREMENT)*GIM_ARRAY_GROW_FACTOR)==false) return false; + } + return true; + } + +//!@} +//! public operations +//!@{ + inline bool reserve(GUINT size) + { + if(m_allocated_size>=size) return false; + return resizeData(size); + } + + inline void clear_range(GUINT start_range) + { + while(m_size>start_range) + { + m_data[--m_size].~T(); + } + } + + inline void clear() + { + if(m_size==0)return; + clear_range(0); + } + + inline void clear_memory() + { + clear(); + destroyData(); + } + + gim_array() + { + m_data = 0; + m_size = 0; + m_allocated_size = 0; + } + + gim_array(GUINT reservesize) + { + m_data = 0; + m_size = 0; + + m_allocated_size = 0; + reserve(reservesize); + } + + ~gim_array() + { + clear_memory(); + } + + inline GUINT size() const + { + return m_size; + } + + inline GUINT max_size() const + { + return m_allocated_size; + } + + inline T & operator[](size_t i) + { + return m_data[i]; + } + inline const T & operator[](size_t i) const + { + return m_data[i]; + } + + inline T * pointer(){ return m_data;} + inline const T * pointer() const + { return m_data;} + + + inline T * get_pointer_at(GUINT i) + { + return m_data + i; + } + + inline const T * get_pointer_at(GUINT i) const + { + return m_data + i; + } + + inline T & at(GUINT i) + { + return m_data[i]; + } + + inline const T & at(GUINT i) const + { + return m_data[i]; + } + + inline T & front() + { + return *m_data; + } + + inline const T & front() const + { + return *m_data; + } + + inline T & back() + { + return m_data[m_size-1]; + } + + inline const T & back() const + { + return m_data[m_size-1]; + } + + + inline void swap(GUINT i, GUINT j) + { + gim_swap_elements(m_data,i,j); + } + + inline void push_back(const T & obj) + { + this->growingCheck(); + m_data[m_size] = obj; + m_size++; + } + + //!Simply increase the m_size, doesn't call the new element constructor + inline void push_back_mem() + { + this->growingCheck(); + m_size++; + } + + inline void push_back_memcpy(const T & obj) + { + this->growingCheck(); + irr_simd_memcpy(&m_data[m_size],&obj,sizeof(T)); + m_size++; + } + + inline void pop_back() + { + m_size--; + m_data[m_size].~T(); + } + + //!Simply decrease the m_size, doesn't call the deleted element destructor + inline void pop_back_mem() + { + m_size--; + } + + //! fast erase + inline void erase(GUINT index) + { + if(indexgrowingCheck(); + for(GUINT i = m_size;i>index;i--) + { + gim_simd_memcpy(m_data+i,m_data+i-1,sizeof(T)); + } + m_size++; + } + + inline void insert(const T & obj,GUINT index) + { + insert_mem(index); + m_data[index] = obj; + } + + inline void resize(GUINT size, bool call_constructor = true) + { + + if(size>m_size) + { + reserve(size); + if(call_constructor) + { + T obj; + while(m_size +SIMD_FORCE_INLINE bool POINT_IN_HULL( + const CLASS_POINT& point,const CLASS_PLANE * planes,GUINT plane_count) +{ + GREAL _dis; + for (GUINT _i = 0;_i< plane_count;++_i) + { + _dis = DISTANCE_PLANE_POINT(planes[_i],point); + if(_dis>0.0f) return false; + } + return true; +} + +template +SIMD_FORCE_INLINE void PLANE_CLIP_SEGMENT( + const CLASS_POINT& s1, + const CLASS_POINT &s2,const CLASS_PLANE &plane,CLASS_POINT &clipped) +{ + GREAL _dis1,_dis2; + _dis1 = DISTANCE_PLANE_POINT(plane,s1); + VEC_DIFF(clipped,s2,s1); + _dis2 = VEC_DOT(clipped,plane); + VEC_SCALE(clipped,-_dis1/_dis2,clipped); + VEC_SUM(clipped,clipped,s1); +} + +enum ePLANE_INTERSECTION_TYPE +{ + G_BACK_PLANE = 0, + G_COLLIDE_PLANE, + G_FRONT_PLANE +}; + +enum eLINE_PLANE_INTERSECTION_TYPE +{ + G_FRONT_PLANE_S1 = 0, + G_FRONT_PLANE_S2, + G_BACK_PLANE_S1, + G_BACK_PLANE_S2, + G_COLLIDE_PLANE_S1, + G_COLLIDE_PLANE_S2 +}; + +//! Confirms if the plane intersect the edge or nor +/*! +intersection type must have the following values +
      +
    • 0 : Segment in front of plane, s1 closest +
    • 1 : Segment in front of plane, s2 closest +
    • 2 : Segment in back of plane, s1 closest +
    • 3 : Segment in back of plane, s2 closest +
    • 4 : Segment collides plane, s1 in back +
    • 5 : Segment collides plane, s2 in back +
    +*/ + +template +SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT2( + const CLASS_POINT& s1, + const CLASS_POINT &s2, + const CLASS_PLANE &plane,CLASS_POINT &clipped) +{ + GREAL _dis1 = DISTANCE_PLANE_POINT(plane,s1); + GREAL _dis2 = DISTANCE_PLANE_POINT(plane,s2); + if(_dis1 >-G_EPSILON && _dis2 >-G_EPSILON) + { + if(_dis1<_dis2) return G_FRONT_PLANE_S1; + return G_FRONT_PLANE_S2; + } + else if(_dis1 _dis2) return G_BACK_PLANE_S1; + return G_BACK_PLANE_S2; + } + + VEC_DIFF(clipped,s2,s1); + _dis2 = VEC_DOT(clipped,plane); + VEC_SCALE(clipped,-_dis1/_dis2,clipped); + VEC_SUM(clipped,clipped,s1); + if(_dis1<_dis2) return G_COLLIDE_PLANE_S1; + return G_COLLIDE_PLANE_S2; +} + +//! Confirms if the plane intersect the edge or not +/*! +clipped1 and clipped2 are the vertices behind the plane. +clipped1 is the closest + +intersection_type must have the following values +
      +
    • 0 : Segment in front of plane, s1 closest +
    • 1 : Segment in front of plane, s2 closest +
    • 2 : Segment in back of plane, s1 closest +
    • 3 : Segment in back of plane, s2 closest +
    • 4 : Segment collides plane, s1 in back +
    • 5 : Segment collides plane, s2 in back +
    +*/ +template +SIMD_FORCE_INLINE eLINE_PLANE_INTERSECTION_TYPE PLANE_CLIP_SEGMENT_CLOSEST( + const CLASS_POINT& s1, + const CLASS_POINT &s2, + const CLASS_PLANE &plane, + CLASS_POINT &clipped1,CLASS_POINT &clipped2) +{ + eLINE_PLANE_INTERSECTION_TYPE intersection_type = PLANE_CLIP_SEGMENT2(s1,s2,plane,clipped1); + switch(intersection_type) + { + case G_FRONT_PLANE_S1: + VEC_COPY(clipped1,s1); + VEC_COPY(clipped2,s2); + break; + case G_FRONT_PLANE_S2: + VEC_COPY(clipped1,s2); + VEC_COPY(clipped2,s1); + break; + case G_BACK_PLANE_S1: + VEC_COPY(clipped1,s1); + VEC_COPY(clipped2,s2); + break; + case G_BACK_PLANE_S2: + VEC_COPY(clipped1,s2); + VEC_COPY(clipped2,s1); + break; + case G_COLLIDE_PLANE_S1: + VEC_COPY(clipped2,s1); + break; + case G_COLLIDE_PLANE_S2: + VEC_COPY(clipped2,s2); + break; + } + return intersection_type; +} + + +//! Finds the 2 smallest cartesian coordinates of a plane normal +#define PLANE_MINOR_AXES(plane, i0, i1) VEC_MINOR_AXES(plane, i0, i1) + +//! Ray plane collision in one way +/*! +Intersects plane in one way only. The ray must face the plane (normals must be in opossite directions).
    +It uses the PLANEDIREPSILON constant. +*/ +template +SIMD_FORCE_INLINE bool RAY_PLANE_COLLISION( + const CLASS_PLANE & plane, + const CLASS_POINT & vDir, + const CLASS_POINT & vPoint, + CLASS_POINT & pout,T &tparam) +{ + GREAL _dis,_dotdir; + _dotdir = VEC_DOT(plane,vDir); + if(_dotdir +SIMD_FORCE_INLINE GUINT LINE_PLANE_COLLISION( + const CLASS_PLANE & plane, + const CLASS_POINT & vDir, + const CLASS_POINT & vPoint, + CLASS_POINT & pout, + T &tparam, + T tmin, T tmax) +{ + GREAL _dis,_dotdir; + _dotdir = VEC_DOT(plane,vDir); + if(btFabs(_dotdir)tmax) + { + returnvalue = 0; + tparam = tmax; + } + + VEC_SCALE(pout,tparam,vDir); + VEC_SUM(pout,vPoint,pout); + return returnvalue; +} + +/*! \brief Returns the Ray on which 2 planes intersect if they do. + Written by Rodrigo Hernandez on ODE convex collision + + \param p1 Plane 1 + \param p2 Plane 2 + \param p Contains the origin of the ray upon returning if planes intersect + \param d Contains the direction of the ray upon returning if planes intersect + \return true if the planes intersect, 0 if paralell. + +*/ +template +SIMD_FORCE_INLINE bool INTERSECT_PLANES( + const CLASS_PLANE &p1, + const CLASS_PLANE &p2, + CLASS_POINT &p, + CLASS_POINT &d) +{ + VEC_CROSS(d,p1,p2); + GREAL denom = VEC_DOT(d, d); + if(GIM_IS_ZERO(denom)) return false; + vec3f _n; + _n[0]=p1[3]*p2[0] - p2[3]*p1[0]; + _n[1]=p1[3]*p2[1] - p2[3]*p1[1]; + _n[2]=p1[3]*p2[2] - p2[3]*p1[2]; + VEC_CROSS(p,_n,d); + p[0]/=denom; + p[1]/=denom; + p[2]/=denom; + return true; +} + +//***************** SEGMENT and LINE FUNCTIONS **********************************/// + +/*! Finds the closest point(cp) to (v) on a segment (e1,e2) + */ +template +SIMD_FORCE_INLINE void CLOSEST_POINT_ON_SEGMENT( + CLASS_POINT & cp, const CLASS_POINT & v, + const CLASS_POINT &e1,const CLASS_POINT &e2) +{ + vec3f _n; + VEC_DIFF(_n,e2,e1); + VEC_DIFF(cp,v,e1); + GREAL _scalar = VEC_DOT(cp, _n); + _scalar/= VEC_DOT(_n, _n); + if(_scalar <0.0f) + { + VEC_COPY(cp,e1); + } + else if(_scalar >1.0f) + { + VEC_COPY(cp,e2); + } + else + { + VEC_SCALE(cp,_scalar,_n); + VEC_SUM(cp,cp,e1); + } +} + + +/*! \brief Finds the line params where these lines intersect. + +\param dir1 Direction of line 1 +\param point1 Point of line 1 +\param dir2 Direction of line 2 +\param point2 Point of line 2 +\param t1 Result Parameter for line 1 +\param t2 Result Parameter for line 2 +\param dointersect 0 if the lines won't intersect, else 1 + +*/ +template +SIMD_FORCE_INLINE bool LINE_INTERSECTION_PARAMS( + const CLASS_POINT & dir1, + CLASS_POINT & point1, + const CLASS_POINT & dir2, + CLASS_POINT & point2, + T& t1,T& t2) +{ + GREAL det; + GREAL e1e1 = VEC_DOT(dir1,dir1); + GREAL e1e2 = VEC_DOT(dir1,dir2); + GREAL e2e2 = VEC_DOT(dir2,dir2); + vec3f p1p2; + VEC_DIFF(p1p2,point1,point2); + GREAL p1p2e1 = VEC_DOT(p1p2,dir1); + GREAL p1p2e2 = VEC_DOT(p1p2,dir2); + det = e1e2*e1e2 - e1e1*e2e2; + if(GIM_IS_ZERO(det)) return false; + t1 = (e1e2*p1p2e2 - e2e2*p1p2e1)/det; + t2 = (e1e1*p1p2e2 - e1e2*p1p2e1)/det; + return true; +} + +//! Find closest points on segments +template +SIMD_FORCE_INLINE void SEGMENT_COLLISION( + const CLASS_POINT & vA1, + const CLASS_POINT & vA2, + const CLASS_POINT & vB1, + const CLASS_POINT & vB2, + CLASS_POINT & vPointA, + CLASS_POINT & vPointB) +{ + CLASS_POINT _AD,_BD,_N; + vec4f _M;//plane + VEC_DIFF(_AD,vA2,vA1); + VEC_DIFF(_BD,vB2,vB1); + VEC_CROSS(_N,_AD,_BD); + GREAL _tp = VEC_DOT(_N,_N); + if(_tp_M[1]) + { + invert_b_order = true; + GIM_SWAP_NUMBERS(_M[0],_M[1]); + } + _M[2] = VEC_DOT(vA1,_AD); + _M[3] = VEC_DOT(vA2,_AD); + //mid points + _N[0] = (_M[0]+_M[1])*0.5f; + _N[1] = (_M[2]+_M[3])*0.5f; + + if(_N[0]<_N[1]) + { + if(_M[1]<_M[2]) + { + vPointB = invert_b_order?vB1:vB2; + vPointA = vA1; + } + else if(_M[1]<_M[3]) + { + vPointB = invert_b_order?vB1:vB2; + CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2); + } + else + { + vPointA = vA2; + CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2); + } + } + else + { + if(_M[3]<_M[0]) + { + vPointB = invert_b_order?vB2:vB1; + vPointA = vA2; + } + else if(_M[3]<_M[1]) + { + vPointA = vA2; + CLOSEST_POINT_ON_SEGMENT(vPointB,vPointA,vB1,vB2); + } + else + { + vPointB = invert_b_order?vB1:vB2; + CLOSEST_POINT_ON_SEGMENT(vPointA,vPointB,vA1,vA2); + } + } + return; + } + + + VEC_CROSS(_M,_N,_BD); + _M[3] = VEC_DOT(_M,vB1); + + LINE_PLANE_COLLISION(_M,_AD,vA1,vPointA,_tp,btScalar(0), btScalar(1)); + /*Closest point on segment*/ + VEC_DIFF(vPointB,vPointA,vB1); + _tp = VEC_DOT(vPointB, _BD); + _tp/= VEC_DOT(_BD, _BD); + _tp = GIM_CLAMP(_tp,0.0f,1.0f); + VEC_SCALE(vPointB,_tp,_BD); + VEC_SUM(vPointB,vPointB,vB1); +} + + + + +//! Line box intersection in one dimension +/*! + +*\param pos Position of the ray +*\param dir Projection of the Direction of the ray +*\param bmin Minimum bound of the box +*\param bmax Maximum bound of the box +*\param tfirst the minimum projection. Assign to 0 at first. +*\param tlast the maximum projection. Assign to INFINITY at first. +*\return true if there is an intersection. +*/ +template +SIMD_FORCE_INLINE bool BOX_AXIS_INTERSECT(T pos, T dir,T bmin, T bmax, T & tfirst, T & tlast) +{ + if(GIM_IS_ZERO(dir)) + { + return !(pos < bmin || pos > bmax); + } + GREAL a0 = (bmin - pos) / dir; + GREAL a1 = (bmax - pos) / dir; + if(a0 > a1) GIM_SWAP_NUMBERS(a0, a1); + tfirst = GIM_MAX(a0, tfirst); + tlast = GIM_MIN(a1, tlast); + if (tlast < tfirst) return false; + return true; +} + + +//! Sorts 3 componets +template +SIMD_FORCE_INLINE void SORT_3_INDICES( + const T * values, + GUINT * order_indices) +{ + //get minimum + order_indices[0] = values[0] < values[1] ? (values[0] < values[2] ? 0 : 2) : (values[1] < values[2] ? 1 : 2); + + //get second and third + GUINT i0 = (order_indices[0] + 1)%3; + GUINT i1 = (i0 + 1)%3; + + if(values[i0] < values[i1]) + { + order_indices[1] = i0; + order_indices[2] = i1; + } + else + { + order_indices[1] = i1; + order_indices[2] = i0; + } +} + + + +//! @} + + +#endif // GIM_VECTOR_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_bitset.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_bitset.h new file mode 100644 index 00000000000..417aa72fe22 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_bitset.h @@ -0,0 +1,129 @@ +#ifndef GIM_BITSET_H_INCLUDED +#define GIM_BITSET_H_INCLUDED +/*! \file gim_bitset.h +\author Francisco León Nájera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "gim_array.h" + +/*! \addtogroup CONTAINERS +\brief +Abstract class for template containers +*/ +//! @{ + +#define GUINT_BIT_COUNT 32 +#define GUINT_EXPONENT 5 + +class gim_bitset +{ +public: + gim_array m_container; + + gim_bitset() + { + + } + + gim_bitset(GUINT bits_count) + { + resize(bits_count); + } + + ~gim_bitset() + { + } + + inline bool resize(GUINT newsize) + { + GUINT oldsize = m_container.size(); + m_container.resize(newsize/GUINT_BIT_COUNT + 1,false); + while(oldsize=size()) + { + resize(bit_index); + } + m_container[bit_index >> GUINT_EXPONENT] |= (1 << (bit_index & (GUINT_BIT_COUNT-1))); + } + + ///Return 0 or 1 + inline char get(GUINT bit_index) + { + if(bit_index>=size()) + { + return 0; + } + char value = m_container[bit_index >> GUINT_EXPONENT] & + (1 << (bit_index & (GUINT_BIT_COUNT-1))); + return value; + } + + inline void clear(GUINT bit_index) + { + m_container[bit_index >> GUINT_EXPONENT] &= ~(1 << (bit_index & (GUINT_BIT_COUNT-1))); + } +}; + + +//! @} + + + +#endif // GIM_CONTAINERS_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_box_collision.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_collision.h new file mode 100644 index 00000000000..4f825cf5208 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_collision.h @@ -0,0 +1,594 @@ +#ifndef GIM_BOX_COLLISION_H_INCLUDED +#define GIM_BOX_COLLISION_H_INCLUDED + +/*! \file gim_box_collision.h +\author Francisco León Nájera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ +#include "gim_basic_geometry_operations.h" +#include "LinearMath/btTransform.h" + +/*! \defgroup BOUND_AABB_OPERATIONS +*/ +//! @{ + + +//SIMD_FORCE_INLINE bool test_cross_edge_box( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, const btVector3 & extend, +// int dir_index0, +// int dir_index1 +// int component_index0, +// int component_index1) +//{ +// // dir coords are -z and y +// +// const btScalar dir0 = -edge[dir_index0]; +// const btScalar dir1 = edge[dir_index1]; +// btScalar pmin = pointa[component_index0]*dir0 + pointa[component_index1]*dir1; +// btScalar pmax = pointb[component_index0]*dir0 + pointb[component_index1]*dir1; +// //find minmax +// if(pmin>pmax) +// { +// GIM_SWAP_NUMBERS(pmin,pmax); +// } +// //find extends +// const btScalar rad = extend[component_index0] * absolute_edge[dir_index0] + +// extend[component_index1] * absolute_edge[dir_index1]; +// +// if(pmin>rad || -rad>pmax) return false; +// return true; +//} +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_X_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,2,1,1,2); +//} +// +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_Y_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,0,2,2,0); +//} +// +//SIMD_FORCE_INLINE bool test_cross_edge_box_Z_axis( +// const btVector3 & edge, +// const btVector3 & absolute_edge, +// const btVector3 & pointa, +// const btVector3 & pointb, btVector3 & extend) +//{ +// +// return test_cross_edge_box(edge,absolute_edge,pointa,pointb,extend,1,0,0,1); +//} + +#define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\ +{\ + const btScalar dir0 = -edge[i_dir_0];\ + const btScalar dir1 = edge[i_dir_1];\ + btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\ + btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\ + if(pmin>pmax)\ + {\ + GIM_SWAP_NUMBERS(pmin,pmax); \ + }\ + const btScalar abs_dir0 = absolute_edge[i_dir_0];\ + const btScalar abs_dir1 = absolute_edge[i_dir_1];\ + const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\ + if(pmin>rad || -rad>pmax) return false;\ +}\ + + +#define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\ +}\ + +#define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\ +}\ + +#define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\ +{\ + TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\ +}\ + + + +//! Class for transforming a model1 to the space of model0 +class GIM_BOX_BOX_TRANSFORM_CACHE +{ +public: + btVector3 m_T1to0;//!< Transforms translation of model1 to model 0 + btMatrix3x3 m_R1to0;//!< Transforms Rotation of model1 to model 0, equal to R0' * R1 + btMatrix3x3 m_AR;//!< Absolute value of m_R1to0 + + SIMD_FORCE_INLINE void calc_absolute_matrix() + { + static const btVector3 vepsi(1e-6f,1e-6f,1e-6f); + m_AR[0] = vepsi + m_R1to0[0].absolute(); + m_AR[1] = vepsi + m_R1to0[1].absolute(); + m_AR[2] = vepsi + m_R1to0[2].absolute(); + } + + GIM_BOX_BOX_TRANSFORM_CACHE() + { + } + + + GIM_BOX_BOX_TRANSFORM_CACHE(mat4f trans1_to_0) + { + COPY_MATRIX_3X3(m_R1to0,trans1_to_0) + MAT_GET_TRANSLATION(trans1_to_0,m_T1to0) + calc_absolute_matrix(); + } + + //! Calc the transformation relative 1 to 0. Inverts matrics by transposing + SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1) + { + + m_R1to0 = trans0.getBasis().transpose(); + m_T1to0 = m_R1to0 * (-trans0.getOrigin()); + + m_T1to0 += m_R1to0*trans1.getOrigin(); + m_R1to0 *= trans1.getBasis(); + + calc_absolute_matrix(); + } + + //! Calcs the full invertion of the matrices. Useful for scaling matrices + SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1) + { + m_R1to0 = trans0.getBasis().inverse(); + m_T1to0 = m_R1to0 * (-trans0.getOrigin()); + + m_T1to0 += m_R1to0*trans1.getOrigin(); + m_R1to0 *= trans1.getBasis(); + + calc_absolute_matrix(); + } + + SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point) + { + return btVector3(m_R1to0[0].dot(point) + m_T1to0.x(), + m_R1to0[1].dot(point) + m_T1to0.y(), + m_R1to0[2].dot(point) + m_T1to0.z()); + } +}; + + +#define BOX_PLANE_EPSILON 0.000001f + +//! Axis aligned box +class GIM_AABB +{ +public: + btVector3 m_min; + btVector3 m_max; + + GIM_AABB() + {} + + + GIM_AABB(const btVector3 & V1, + const btVector3 & V2, + const btVector3 & V3) + { + m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]); + } + + GIM_AABB(const btVector3 & V1, + const btVector3 & V2, + const btVector3 & V3, + GREAL margin) + { + m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]); + + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + GIM_AABB(const GIM_AABB &other): + m_min(other.m_min),m_max(other.m_max) + { + } + + GIM_AABB(const GIM_AABB &other,btScalar margin ): + m_min(other.m_min),m_max(other.m_max) + { + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + SIMD_FORCE_INLINE void invalidate() + { + m_min[0] = G_REAL_INFINITY; + m_min[1] = G_REAL_INFINITY; + m_min[2] = G_REAL_INFINITY; + m_max[0] = -G_REAL_INFINITY; + m_max[1] = -G_REAL_INFINITY; + m_max[2] = -G_REAL_INFINITY; + } + + SIMD_FORCE_INLINE void increment_margin(btScalar margin) + { + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + SIMD_FORCE_INLINE void copy_with_margin(const GIM_AABB &other, btScalar margin) + { + m_min[0] = other.m_min[0] - margin; + m_min[1] = other.m_min[1] - margin; + m_min[2] = other.m_min[2] - margin; + + m_max[0] = other.m_max[0] + margin; + m_max[1] = other.m_max[1] + margin; + m_max[2] = other.m_max[2] + margin; + } + + template + SIMD_FORCE_INLINE void calc_from_triangle( + const CLASS_POINT & V1, + const CLASS_POINT & V2, + const CLASS_POINT & V3) + { + m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]); + } + + template + SIMD_FORCE_INLINE void calc_from_triangle_margin( + const CLASS_POINT & V1, + const CLASS_POINT & V2, + const CLASS_POINT & V3, btScalar margin) + { + m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]); + m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]); + m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]); + + m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]); + m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]); + m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]); + + m_min[0] -= margin; + m_min[1] -= margin; + m_min[2] -= margin; + m_max[0] += margin; + m_max[1] += margin; + m_max[2] += margin; + } + + //! Apply a transform to an AABB + SIMD_FORCE_INLINE void appy_transform(const btTransform & trans) + { + btVector3 center = (m_max+m_min)*0.5f; + btVector3 extends = m_max - center; + // Compute new center + center = trans(center); + + btVector3 textends(extends.dot(trans.getBasis().getRow(0).absolute()), + extends.dot(trans.getBasis().getRow(1).absolute()), + extends.dot(trans.getBasis().getRow(2).absolute())); + + m_min = center - textends; + m_max = center + textends; + } + + //! Merges a Box + SIMD_FORCE_INLINE void merge(const GIM_AABB & box) + { + m_min[0] = GIM_MIN(m_min[0],box.m_min[0]); + m_min[1] = GIM_MIN(m_min[1],box.m_min[1]); + m_min[2] = GIM_MIN(m_min[2],box.m_min[2]); + + m_max[0] = GIM_MAX(m_max[0],box.m_max[0]); + m_max[1] = GIM_MAX(m_max[1],box.m_max[1]); + m_max[2] = GIM_MAX(m_max[2],box.m_max[2]); + } + + //! Merges a point + template + SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point) + { + m_min[0] = GIM_MIN(m_min[0],point[0]); + m_min[1] = GIM_MIN(m_min[1],point[1]); + m_min[2] = GIM_MIN(m_min[2],point[2]); + + m_max[0] = GIM_MAX(m_max[0],point[0]); + m_max[1] = GIM_MAX(m_max[1],point[1]); + m_max[2] = GIM_MAX(m_max[2],point[2]); + } + + //! Gets the extend and center + SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const + { + center = (m_max+m_min)*0.5f; + extend = m_max - center; + } + + //! Finds the intersecting box between this box and the other. + SIMD_FORCE_INLINE void find_intersection(const GIM_AABB & other, GIM_AABB & intersection) const + { + intersection.m_min[0] = GIM_MAX(other.m_min[0],m_min[0]); + intersection.m_min[1] = GIM_MAX(other.m_min[1],m_min[1]); + intersection.m_min[2] = GIM_MAX(other.m_min[2],m_min[2]); + + intersection.m_max[0] = GIM_MIN(other.m_max[0],m_max[0]); + intersection.m_max[1] = GIM_MIN(other.m_max[1],m_max[1]); + intersection.m_max[2] = GIM_MIN(other.m_max[2],m_max[2]); + } + + + SIMD_FORCE_INLINE bool has_collision(const GIM_AABB & other) const + { + if(m_min[0] > other.m_max[0] || + m_max[0] < other.m_min[0] || + m_min[1] > other.m_max[1] || + m_max[1] < other.m_min[1] || + m_min[2] > other.m_max[2] || + m_max[2] < other.m_min[2]) + { + return false; + } + return true; + } + + /*! \brief Finds the Ray intersection parameter. + \param aabb Aligned box + \param vorigin A vec3f with the origin of the ray + \param vdir A vec3f with the direction of the ray + */ + SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir) + { + btVector3 extents,center; + this->get_center_extend(center,extents);; + + btScalar Dx = vorigin[0] - center[0]; + if(GIM_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false; + btScalar Dy = vorigin[1] - center[1]; + if(GIM_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false; + btScalar Dz = vorigin[2] - center[2]; + if(GIM_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false; + + + btScalar f = vdir[1] * Dz - vdir[2] * Dy; + if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false; + f = vdir[2] * Dx - vdir[0] * Dz; + if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false; + f = vdir[0] * Dy - vdir[1] * Dx; + if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false; + return true; + } + + + SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const + { + btVector3 center = (m_max+m_min)*0.5f; + btVector3 extend = m_max-center; + + btScalar _fOrigin = direction.dot(center); + btScalar _fMaximumExtent = extend.dot(direction.absolute()); + vmin = _fOrigin - _fMaximumExtent; + vmax = _fOrigin + _fMaximumExtent; + } + + SIMD_FORCE_INLINE ePLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const + { + btScalar _fmin,_fmax; + this->projection_interval(plane,_fmin,_fmax); + + if(plane[3] > _fmax + BOX_PLANE_EPSILON) + { + return G_BACK_PLANE; // 0 + } + + if(plane[3]+BOX_PLANE_EPSILON >=_fmin) + { + return G_COLLIDE_PLANE; //1 + } + return G_FRONT_PLANE;//2 + } + + SIMD_FORCE_INLINE bool overlapping_trans_conservative(const GIM_AABB & box, btTransform & trans1_to_0) + { + GIM_AABB tbox = box; + tbox.appy_transform(trans1_to_0); + return has_collision(tbox); + } + + //! transcache is the transformation cache from box to this AABB + SIMD_FORCE_INLINE bool overlapping_trans_cache( + const GIM_AABB & box,const GIM_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest) + { + + //Taken from OPCODE + btVector3 ea,eb;//extends + btVector3 ca,cb;//extends + get_center_extend(ca,ea); + box.get_center_extend(cb,eb); + + + btVector3 T; + btScalar t,t2; + int i; + + // Class I : A's basis vectors + for(i=0;i<3;i++) + { + T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i]; + t = transcache.m_AR[i].dot(eb) + ea[i]; + if(GIM_GREATER(T[i], t)) return false; + } + // Class II : B's basis vectors + for(i=0;i<3;i++) + { + t = MAT_DOT_COL(transcache.m_R1to0,T,i); + t2 = MAT_DOT_COL(transcache.m_AR,ea,i) + eb[i]; + if(GIM_GREATER(t,t2)) return false; + } + // Class III : 9 cross products + if(fulltest) + { + int j,m,n,o,p,q,r; + for(i=0;i<3;i++) + { + m = (i+1)%3; + n = (i+2)%3; + o = i==0?1:0; + p = i==2?1:2; + for(j=0;j<3;j++) + { + q = j==2?1:2; + r = j==0?1:0; + t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j]; + t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] + + eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r]; + if(GIM_GREATER(t,t2)) return false; + } + } + } + return true; + } + + //! Simple test for planes. + SIMD_FORCE_INLINE bool collide_plane( + const btVector4 & plane) + { + ePLANE_INTERSECTION_TYPE classify = plane_classify(plane); + return (classify == G_COLLIDE_PLANE); + } + + //! test for a triangle, with edges + SIMD_FORCE_INLINE bool collide_triangle_exact( + const btVector3 & p1, + const btVector3 & p2, + const btVector3 & p3, + const btVector4 & triangle_plane) + { + if(!collide_plane(triangle_plane)) return false; + + btVector3 center,extends; + this->get_center_extend(center,extends); + + const btVector3 v1(p1 - center); + const btVector3 v2(p2 - center); + const btVector3 v3(p3 - center); + + //First axis + btVector3 diff(v2 - v1); + btVector3 abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends); + + + diff = v3 - v2; + abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends); + + diff = v1 - v3; + abs_diff = diff.absolute(); + //Test With X axis + TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends); + //Test With Y axis + TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends); + //Test With Z axis + TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends); + + return true; + } +}; + + +//! Compairison of transformation objects +SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2) +{ + if(!(t1.getOrigin() == t2.getOrigin()) ) return false; + + if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false; + if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false; + if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false; + return true; +} + + +//! @} + +#endif // GIM_BOX_COLLISION_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.cpp b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.cpp new file mode 100644 index 00000000000..1ffc2bbad78 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.cpp @@ -0,0 +1,182 @@ + +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + + +#include "gim_box_set.h" + + +GUINT GIM_BOX_TREE::_calc_splitting_axis( + gim_array & primitive_boxes, GUINT startIndex, GUINT endIndex) +{ + GUINT i; + + btVector3 means(btScalar(0.),btScalar(0.),btScalar(0.)); + btVector3 variance(btScalar(0.),btScalar(0.),btScalar(0.)); + GUINT numIndices = endIndex-startIndex; + + for (i=startIndex;i & primitive_boxes, GUINT startIndex, + GUINT endIndex, GUINT splitAxis) +{ + GUINT i; + GUINT splitIndex =startIndex; + GUINT numIndices = endIndex - startIndex; + + // average of centers + btScalar splitValue = 0.0f; + for (i=startIndex;i splitValue) + { + //swap + primitive_boxes.swap(i,splitIndex); + splitIndex++; + } + } + + //if the splitIndex causes unbalanced trees, fix this by using the center in between startIndex and endIndex + //otherwise the tree-building might fail due to stack-overflows in certain cases. + //unbalanced1 is unsafe: it can cause stack overflows + //bool unbalanced1 = ((splitIndex==startIndex) || (splitIndex == (endIndex-1))); + + //unbalanced2 should work too: always use center (perfect balanced trees) + //bool unbalanced2 = true; + + //this should be safe too: + GUINT rangeBalancedIndices = numIndices/3; + bool unbalanced = ((splitIndex<=(startIndex+rangeBalancedIndices)) || (splitIndex >=(endIndex-1-rangeBalancedIndices))); + + if (unbalanced) + { + splitIndex = startIndex+ (numIndices>>1); + } + + bool unbal = (splitIndex==startIndex) || (splitIndex == (endIndex)); + btAssert(!unbal); + + return splitIndex; +} + + +void GIM_BOX_TREE::_build_sub_tree(gim_array & primitive_boxes, GUINT startIndex, GUINT endIndex) +{ + GUINT current_index = m_num_nodes++; + + btAssert((endIndex-startIndex)>0); + + if((endIndex-startIndex) == 1) //we got a leaf + { + m_node_array[current_index].m_left = 0; + m_node_array[current_index].m_right = 0; + m_node_array[current_index].m_escapeIndex = 0; + + m_node_array[current_index].m_bound = primitive_boxes[startIndex].m_bound; + m_node_array[current_index].m_data = primitive_boxes[startIndex].m_data; + return; + } + + //configure inner node + + GUINT splitIndex; + + //calc this node bounding box + m_node_array[current_index].m_bound.invalidate(); + for (splitIndex=startIndex;splitIndex & primitive_boxes) +{ + // initialize node count to 0 + m_num_nodes = 0; + // allocate nodes + m_node_array.resize(primitive_boxes.size()*2); + + _build_sub_tree(primitive_boxes, 0, primitive_boxes.size()); +} + diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.h new file mode 100644 index 00000000000..1c6c3955f8b --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_box_set.h @@ -0,0 +1,678 @@ +#ifndef GIM_BOX_SET_H_INCLUDED +#define GIM_BOX_SET_H_INCLUDED + +/*! \file gim_box_set.h +\author Francisco León Nájera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + + +#include "gim_array.h" +#include "gim_radixsort.h" +#include "gim_box_collision.h" +#include "gim_tri_collision.h" + + +/*! \defgroup BOX_PRUNNING + + + +*/ +//! @{ + +//! Overlapping pair +struct GIM_PAIR +{ + GUINT m_index1; + GUINT m_index2; + GIM_PAIR() + {} + + GIM_PAIR(const GIM_PAIR & p) + { + m_index1 = p.m_index1; + m_index2 = p.m_index2; + } + + GIM_PAIR(GUINT index1, GUINT index2) + { + m_index1 = index1; + m_index2 = index2; + } +}; + +//! A pairset array +class gim_pair_set: public gim_array +{ +public: + gim_pair_set():gim_array(32) + { + } + inline void push_pair(GUINT index1,GUINT index2) + { + push_back(GIM_PAIR(index1,index2)); + } + + inline void push_pair_inv(GUINT index1,GUINT index2) + { + push_back(GIM_PAIR(index2,index1)); + } +}; + + +//! Prototype Base class for primitive classification +/*! +This class is a wrapper for primitive collections. +This tells relevant info for the Bounding Box set classes, which take care of space classification. +This class can manage Compound shapes and trimeshes, and if it is managing trimesh then the Hierarchy Bounding Box classes will take advantage of primitive Vs Box overlapping tests for getting optimal results and less Per Box compairisons. +*/ +class GIM_PRIMITIVE_MANAGER_PROTOTYPE +{ +public: + + //! determines if this manager consist on only triangles, which special case will be optimized + virtual bool is_trimesh() = 0; + virtual GUINT get_primitive_count() = 0; + virtual void get_primitive_box(GUINT prim_index ,GIM_AABB & primbox) = 0; + virtual void get_primitive_triangle(GUINT prim_index,GIM_TRIANGLE & triangle) = 0; +}; + + +struct GIM_AABB_DATA +{ + GIM_AABB m_bound; + GUINT m_data; +}; + +//! Node Structure for trees +struct GIM_BOX_TREE_NODE +{ + GIM_AABB m_bound; + GUINT m_left;//!< Left subtree + GUINT m_right;//!< Right subtree + GUINT m_escapeIndex;//!< Scape index for traversing + GUINT m_data;//!< primitive index if apply + + GIM_BOX_TREE_NODE() + { + m_left = 0; + m_right = 0; + m_escapeIndex = 0; + m_data = 0; + } + + SIMD_FORCE_INLINE bool is_leaf_node() const + { + return (!m_left && !m_right); + } +}; + +//! Basic Box tree structure +class GIM_BOX_TREE +{ +protected: + GUINT m_num_nodes; + gim_array m_node_array; +protected: + GUINT _sort_and_calc_splitting_index( + gim_array & primitive_boxes, + GUINT startIndex, GUINT endIndex, GUINT splitAxis); + + GUINT _calc_splitting_axis(gim_array & primitive_boxes, GUINT startIndex, GUINT endIndex); + + void _build_sub_tree(gim_array & primitive_boxes, GUINT startIndex, GUINT endIndex); +public: + GIM_BOX_TREE() + { + m_num_nodes = 0; + } + + //! prototype functions for box tree management + //!@{ + void build_tree(gim_array & primitive_boxes); + + SIMD_FORCE_INLINE void clearNodes() + { + m_node_array.clear(); + m_num_nodes = 0; + } + + //! node count + SIMD_FORCE_INLINE GUINT getNodeCount() const + { + return m_num_nodes; + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const + { + return m_node_array[nodeindex].is_leaf_node(); + } + + SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const + { + return m_node_array[nodeindex].m_data; + } + + SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const + { + bound = m_node_array[nodeindex].m_bound; + } + + SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound) + { + m_node_array[nodeindex].m_bound = bound; + } + + SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const + { + return m_node_array[nodeindex].m_left; + } + + SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const + { + return m_node_array[nodeindex].m_right; + } + + SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const + { + return m_node_array[nodeindex].m_escapeIndex; + } + + //!@} +}; + + +//! Generic Box Tree Template +/*! +This class offers an structure for managing a box tree of primitives. +Requires a Primitive prototype (like GIM_PRIMITIVE_MANAGER_PROTOTYPE ) and +a Box tree structure ( like GIM_BOX_TREE). +*/ +template +class GIM_BOX_TREE_TEMPLATE_SET +{ +protected: + _GIM_PRIMITIVE_MANAGER_PROTOTYPE m_primitive_manager; + _GIM_BOX_TREE_PROTOTYPE m_box_tree; +protected: + //stackless refit + SIMD_FORCE_INLINE void refit() + { + GUINT nodecount = getNodeCount(); + while(nodecount--) + { + if(isLeafNode(nodecount)) + { + GIM_AABB leafbox; + m_primitive_manager.get_primitive_box(getNodeData(nodecount),leafbox); + setNodeBound(nodecount,leafbox); + } + else + { + //get left bound + GUINT childindex = getLeftNodeIndex(nodecount); + GIM_AABB bound; + getNodeBound(childindex,bound); + //get right bound + childindex = getRightNodeIndex(nodecount); + GIM_AABB bound2; + getNodeBound(childindex,bound2); + bound.merge(bound2); + + setNodeBound(nodecount,bound); + } + } + } +public: + + GIM_BOX_TREE_TEMPLATE_SET() + { + } + + SIMD_FORCE_INLINE GIM_AABB getGlobalBox() const + { + GIM_AABB totalbox; + getNodeBound(0, totalbox); + return totalbox; + } + + SIMD_FORCE_INLINE void setPrimitiveManager(const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & primitive_manager) + { + m_primitive_manager = primitive_manager; + } + + const _GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager() const + { + return m_primitive_manager; + } + + _GIM_PRIMITIVE_MANAGER_PROTOTYPE & getPrimitiveManager() + { + return m_primitive_manager; + } + +//! node manager prototype functions +///@{ + + //! this attemps to refit the box set. + SIMD_FORCE_INLINE void update() + { + refit(); + } + + //! this rebuild the entire set + SIMD_FORCE_INLINE void buildSet() + { + //obtain primitive boxes + gim_array primitive_boxes; + primitive_boxes.resize(m_primitive_manager.get_primitive_count(),false); + + for (GUINT i = 0;i & collided_results) const + { + GUINT curIndex = 0; + GUINT numNodes = getNodeCount(); + + while (curIndex < numNodes) + { + GIM_AABB bound; + getNodeBound(curIndex,bound); + + //catch bugs in tree data + + bool aabbOverlap = bound.has_collision(box); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData(curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getScapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; + } + + //! returns the indices of the primitives in the m_primitive_manager + SIMD_FORCE_INLINE bool boxQueryTrans(const GIM_AABB & box, + const btTransform & transform, gim_array & collided_results) const + { + GIM_AABB transbox=box; + transbox.appy_transform(transform); + return boxQuery(transbox,collided_results); + } + + //! returns the indices of the primitives in the m_primitive_manager + SIMD_FORCE_INLINE bool rayQuery( + const btVector3 & ray_dir,const btVector3 & ray_origin , + gim_array & collided_results) const + { + GUINT curIndex = 0; + GUINT numNodes = getNodeCount(); + + while (curIndex < numNodes) + { + GIM_AABB bound; + getNodeBound(curIndex,bound); + + //catch bugs in tree data + + bool aabbOverlap = bound.collide_ray(ray_origin,ray_dir); + bool isleafnode = isLeafNode(curIndex); + + if (isleafnode && aabbOverlap) + { + collided_results.push_back(getNodeData( curIndex)); + } + + if (aabbOverlap || isleafnode) + { + //next subnode + curIndex++; + } + else + { + //skip node + curIndex+= getScapeNodeIndex(curIndex); + } + } + if(collided_results.size()>0) return true; + return false; + } + + //! tells if this set has hierarcht + SIMD_FORCE_INLINE bool hasHierarchy() const + { + return true; + } + + //! tells if this set is a trimesh + SIMD_FORCE_INLINE bool isTrimesh() const + { + return m_primitive_manager.is_trimesh(); + } + + //! node count + SIMD_FORCE_INLINE GUINT getNodeCount() const + { + return m_box_tree.getNodeCount(); + } + + //! tells if the node is a leaf + SIMD_FORCE_INLINE bool isLeafNode(GUINT nodeindex) const + { + return m_box_tree.isLeafNode(nodeindex); + } + + SIMD_FORCE_INLINE GUINT getNodeData(GUINT nodeindex) const + { + return m_box_tree.getNodeData(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeBound(GUINT nodeindex, GIM_AABB & bound) const + { + m_box_tree.getNodeBound(nodeindex, bound); + } + + SIMD_FORCE_INLINE void setNodeBound(GUINT nodeindex, const GIM_AABB & bound) + { + m_box_tree.setNodeBound(nodeindex, bound); + } + + SIMD_FORCE_INLINE GUINT getLeftNodeIndex(GUINT nodeindex) const + { + return m_box_tree.getLeftNodeIndex(nodeindex); + } + + SIMD_FORCE_INLINE GUINT getRightNodeIndex(GUINT nodeindex) const + { + return m_box_tree.getRightNodeIndex(nodeindex); + } + + SIMD_FORCE_INLINE GUINT getScapeNodeIndex(GUINT nodeindex) const + { + return m_box_tree.getScapeNodeIndex(nodeindex); + } + + SIMD_FORCE_INLINE void getNodeTriangle(GUINT nodeindex,GIM_TRIANGLE & triangle) const + { + m_primitive_manager.get_primitive_triangle(getNodeData(nodeindex),triangle); + } + +//! @} +}; + +//! Class for Box Tree Sets +/*! +this has the GIM_BOX_TREE implementation for bounding boxes. +*/ +template +class GIM_BOX_TREE_SET: public GIM_BOX_TREE_TEMPLATE_SET< _GIM_PRIMITIVE_MANAGER_PROTOTYPE, GIM_BOX_TREE> +{ +public: + +}; + + + + + +/// GIM_BOX_SET collision methods +template +class GIM_TREE_TREE_COLLIDER +{ +public: + gim_pair_set * m_collision_pairs; + BOX_SET_CLASS0 * m_boxset0; + BOX_SET_CLASS1 * m_boxset1; + GUINT current_node0; + GUINT current_node1; + bool node0_is_leaf; + bool node1_is_leaf; + bool t0_is_trimesh; + bool t1_is_trimesh; + bool node0_has_triangle; + bool node1_has_triangle; + GIM_AABB m_box0; + GIM_AABB m_box1; + GIM_BOX_BOX_TRANSFORM_CACHE trans_cache_1to0; + btTransform trans_cache_0to1; + GIM_TRIANGLE m_tri0; + btVector4 m_tri0_plane; + GIM_TRIANGLE m_tri1; + btVector4 m_tri1_plane; + + +public: + GIM_TREE_TREE_COLLIDER() + { + current_node0 = G_UINT_INFINITY; + current_node1 = G_UINT_INFINITY; + } +protected: + SIMD_FORCE_INLINE void retrieve_node0_triangle(GUINT node0) + { + if(node0_has_triangle) return; + m_boxset0->getNodeTriangle(node0,m_tri0); + //transform triangle + m_tri0.m_vertices[0] = trans_cache_0to1(m_tri0.m_vertices[0]); + m_tri0.m_vertices[1] = trans_cache_0to1(m_tri0.m_vertices[1]); + m_tri0.m_vertices[2] = trans_cache_0to1(m_tri0.m_vertices[2]); + m_tri0.get_plane(m_tri0_plane); + + node0_has_triangle = true; + } + + SIMD_FORCE_INLINE void retrieve_node1_triangle(GUINT node1) + { + if(node1_has_triangle) return; + m_boxset1->getNodeTriangle(node1,m_tri1); + //transform triangle + m_tri1.m_vertices[0] = trans_cache_1to0.transform(m_tri1.m_vertices[0]); + m_tri1.m_vertices[1] = trans_cache_1to0.transform(m_tri1.m_vertices[1]); + m_tri1.m_vertices[2] = trans_cache_1to0.transform(m_tri1.m_vertices[2]); + m_tri1.get_plane(m_tri1_plane); + + node1_has_triangle = true; + } + + SIMD_FORCE_INLINE void retrieve_node0_info(GUINT node0) + { + if(node0 == current_node0) return; + m_boxset0->getNodeBound(node0,m_box0); + node0_is_leaf = m_boxset0->isLeafNode(node0); + node0_has_triangle = false; + current_node0 = node0; + } + + SIMD_FORCE_INLINE void retrieve_node1_info(GUINT node1) + { + if(node1 == current_node1) return; + m_boxset1->getNodeBound(node1,m_box1); + node1_is_leaf = m_boxset1->isLeafNode(node1); + node1_has_triangle = false; + current_node1 = node1; + } + + SIMD_FORCE_INLINE bool node_collision(GUINT node0 ,GUINT node1) + { + retrieve_node0_info(node0); + retrieve_node1_info(node1); + bool result = m_box0.overlapping_trans_cache(m_box1,trans_cache_1to0,true); + if(!result) return false; + + if(t0_is_trimesh && node0_is_leaf) + { + //perform primitive vs box collision + retrieve_node0_triangle(node0); + //do triangle vs box collision + m_box1.increment_margin(m_tri0.m_margin); + + result = m_box1.collide_triangle_exact( + m_tri0.m_vertices[0],m_tri0.m_vertices[1],m_tri0.m_vertices[2],m_tri0_plane); + + m_box1.increment_margin(-m_tri0.m_margin); + + if(!result) return false; + return true; + } + else if(t1_is_trimesh && node1_is_leaf) + { + //perform primitive vs box collision + retrieve_node1_triangle(node1); + //do triangle vs box collision + m_box0.increment_margin(m_tri1.m_margin); + + result = m_box0.collide_triangle_exact( + m_tri1.m_vertices[0],m_tri1.m_vertices[1],m_tri1.m_vertices[2],m_tri1_plane); + + m_box0.increment_margin(-m_tri1.m_margin); + + if(!result) return false; + return true; + } + return true; + } + + //stackless collision routine + void find_collision_pairs() + { + gim_pair_set stack_collisions; + stack_collisions.reserve(32); + + //add the first pair + stack_collisions.push_pair(0,0); + + + while(stack_collisions.size()) + { + //retrieve the last pair and pop + GUINT node0 = stack_collisions.back().m_index1; + GUINT node1 = stack_collisions.back().m_index2; + stack_collisions.pop_back(); + if(node_collision(node0,node1)) // a collision is found + { + if(node0_is_leaf) + { + if(node1_is_leaf) + { + m_collision_pairs->push_pair(m_boxset0->getNodeData(node0),m_boxset1->getNodeData(node1)); + } + else + { + //collide left + stack_collisions.push_pair(node0,m_boxset1->getLeftNodeIndex(node1)); + + //collide right + stack_collisions.push_pair(node0,m_boxset1->getRightNodeIndex(node1)); + } + } + else + { + if(node1_is_leaf) + { + //collide left + stack_collisions.push_pair(m_boxset0->getLeftNodeIndex(node0),node1); + //collide right + stack_collisions.push_pair(m_boxset0->getRightNodeIndex(node0),node1); + } + else + { + GUINT left0 = m_boxset0->getLeftNodeIndex(node0); + GUINT right0 = m_boxset0->getRightNodeIndex(node0); + GUINT left1 = m_boxset1->getLeftNodeIndex(node1); + GUINT right1 = m_boxset1->getRightNodeIndex(node1); + //collide left + stack_collisions.push_pair(left0,left1); + //collide right + stack_collisions.push_pair(left0,right1); + //collide left + stack_collisions.push_pair(right0,left1); + //collide right + stack_collisions.push_pair(right0,right1); + + }// else if node1 is not a leaf + }// else if node0 is not a leaf + + }// if(node_collision(node0,node1)) + }//while(stack_collisions.size()) + } +public: + void find_collision(BOX_SET_CLASS0 * boxset1, const btTransform & trans1, + BOX_SET_CLASS1 * boxset2, const btTransform & trans2, + gim_pair_set & collision_pairs, bool complete_primitive_tests = true) + { + m_collision_pairs = &collision_pairs; + m_boxset0 = boxset1; + m_boxset1 = boxset2; + + trans_cache_1to0.calc_from_homogenic(trans1,trans2); + + trans_cache_0to1 = trans2.inverse(); + trans_cache_0to1 *= trans1; + + + if(complete_primitive_tests) + { + t0_is_trimesh = boxset1->getPrimitiveManager().is_trimesh(); + t1_is_trimesh = boxset2->getPrimitiveManager().is_trimesh(); + } + else + { + t0_is_trimesh = false; + t1_is_trimesh = false; + } + + find_collision_pairs(); + } +}; + + +#endif // GIM_BOXPRUNING_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_clip_polygon.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_clip_polygon.h new file mode 100644 index 00000000000..f833732e61a --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_clip_polygon.h @@ -0,0 +1,214 @@ +#ifndef GIM_CLIP_POLYGON_H_INCLUDED +#define GIM_CLIP_POLYGON_H_INCLUDED + +/*! \file gim_tri_collision.h +\author Francisco León Nájera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +/*! \addtogroup GEOMETRIC_OPERATIONS +*/ +//! @{ + +//! This function calcs the distance from a 3D plane +class DISTANCE_PLANE_3D_FUNC +{ +public: + template + inline GREAL operator()(const CLASS_PLANE & plane, const CLASS_POINT & point) + { + return DISTANCE_PLANE_POINT(plane, point); + } +}; + + + +template +SIMD_FORCE_INLINE void PLANE_CLIP_POLYGON_COLLECT( + const CLASS_POINT & point0, + const CLASS_POINT & point1, + GREAL dist0, + GREAL dist1, + CLASS_POINT * clipped, + GUINT & clipped_count) +{ + GUINT _prevclassif = (dist0>G_EPSILON); + GUINT _classif = (dist1>G_EPSILON); + if(_classif!=_prevclassif) + { + GREAL blendfactor = -dist0/(dist1-dist0); + VEC_BLEND(clipped[clipped_count],point0,point1,blendfactor); + clipped_count++; + } + if(!_classif) + { + VEC_COPY(clipped[clipped_count],point1); + clipped_count++; + } +} + + +//! Clips a polygon by a plane +/*! +*\return The count of the clipped counts +*/ +template +SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON_GENERIC( + const CLASS_PLANE & plane, + const CLASS_POINT * polygon_points, + GUINT polygon_point_count, + CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func) +{ + GUINT clipped_count = 0; + + + //clip first point + GREAL firstdist = distance_func(plane,polygon_points[0]);; + if(!(firstdist>G_EPSILON)) + { + VEC_COPY(clipped[clipped_count],polygon_points[0]); + clipped_count++; + } + + GREAL olddist = firstdist; + for(GUINT _i=1;_i +SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE_GENERIC( + const CLASS_PLANE & plane, + const CLASS_POINT & point0, + const CLASS_POINT & point1, + const CLASS_POINT & point2, + CLASS_POINT * clipped,DISTANCE_PLANE_FUNC distance_func) +{ + GUINT clipped_count = 0; + + //clip first point + GREAL firstdist = distance_func(plane,point0);; + if(!(firstdist>G_EPSILON)) + { + VEC_COPY(clipped[clipped_count],point0); + clipped_count++; + } + + // point 1 + GREAL olddist = firstdist; + GREAL dist = distance_func(plane,point1); + + PLANE_CLIP_POLYGON_COLLECT( + point0,point1, + olddist, + dist, + clipped, + clipped_count); + + olddist = dist; + + + // point 2 + dist = distance_func(plane,point2); + + PLANE_CLIP_POLYGON_COLLECT( + point1,point2, + olddist, + dist, + clipped, + clipped_count); + olddist = dist; + + + + //RETURN TO FIRST point + PLANE_CLIP_POLYGON_COLLECT( + point2,point0, + olddist, + firstdist, + clipped, + clipped_count); + + return clipped_count; +} + + +template +SIMD_FORCE_INLINE GUINT PLANE_CLIP_POLYGON3D( + const CLASS_PLANE & plane, + const CLASS_POINT * polygon_points, + GUINT polygon_point_count, + CLASS_POINT * clipped) +{ + return PLANE_CLIP_POLYGON_GENERIC(plane,polygon_points,polygon_point_count,clipped,DISTANCE_PLANE_3D_FUNC()); +} + + +template +SIMD_FORCE_INLINE GUINT PLANE_CLIP_TRIANGLE3D( + const CLASS_PLANE & plane, + const CLASS_POINT & point0, + const CLASS_POINT & point1, + const CLASS_POINT & point2, + CLASS_POINT * clipped) +{ + return PLANE_CLIP_TRIANGLE_GENERIC(plane,point0,point1,point2,clipped,DISTANCE_PLANE_3D_FUNC()); +} + + +//! @} + +#endif // GIM_TRI_COLLISION_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_contact.cpp b/extern/bullet2/src/BulletCollision/Gimpact/gim_contact.cpp new file mode 100644 index 00000000000..20e41de089f --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_contact.cpp @@ -0,0 +1,146 @@ + +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "gim_contact.h" + +#define MAX_COINCIDENT 8 + +void gim_contact_array::merge_contacts( + const gim_contact_array & contacts, bool normal_contact_average) +{ + clear(); + + if(contacts.size()==1) + { + push_back(contacts.back()); + return; + } + + gim_array keycontacts(contacts.size()); + keycontacts.resize(contacts.size(),false); + + //fill key contacts + + GUINT i; + + for (i = 0;im_depth - CONTACT_DIFF_EPSILON > scontact->m_depth)//) + { + *pcontact = *scontact; + coincident_count = 0; + } + else if(normal_contact_average) + { + if(btFabs(pcontact->m_depth - scontact->m_depth)m_normal; + coincident_count++; + } + } + } + } + else + {//add new contact + + if(normal_contact_average && coincident_count>0) + { + pcontact->interpolate_normals(coincident_normals,coincident_count); + coincident_count = 0; + } + + push_back(*scontact); + pcontact = &back(); + } + last_key = key; + } +} + +void gim_contact_array::merge_contacts_unique(const gim_contact_array & contacts) +{ + clear(); + + if(contacts.size()==1) + { + push_back(contacts.back()); + return; + } + + GIM_CONTACT average_contact = contacts.back(); + + for (GUINT i=1;i +
  3. Contact lists must be create by calling \ref GIM_CREATE_CONTACT_LIST +
  4. After querys, contact lists must be destroy by calling \ref GIM_DYNARRAY_DESTROY +
  5. Contacts can be merge for avoid duplicate results by calling \ref gim_merge_contacts + + +*/ +//! @{ + +/** +Configuration var for applying interpolation of contact normals +*/ +#define NORMAL_CONTACT_AVERAGE 1 +#define CONTACT_DIFF_EPSILON 0.00001f + +/// Structure for collision results +class GIM_CONTACT +{ +public: + btVector3 m_point; + btVector3 m_normal; + GREAL m_depth;//Positive value indicates interpenetration + GREAL m_distance;//Padding not for use + GUINT m_feature1;//Face number + GUINT m_feature2;//Face number +public: + GIM_CONTACT() + { + } + + GIM_CONTACT(const GIM_CONTACT & contact): + m_point(contact.m_point), + m_normal(contact.m_normal), + m_depth(contact.m_depth), + m_feature1(contact.m_feature1), + m_feature2(contact.m_feature2) + { + m_point = contact.m_point; + m_normal = contact.m_normal; + m_depth = contact.m_depth; + m_feature1 = contact.m_feature1; + m_feature2 = contact.m_feature2; + } + + GIM_CONTACT(const btVector3 &point,const btVector3 & normal, + GREAL depth, GUINT feature1, GUINT feature2): + m_point(point), + m_normal(normal), + m_depth(depth), + m_feature1(feature1), + m_feature2(feature2) + { + } + + //! Calcs key for coord classification + SIMD_FORCE_INLINE GUINT calc_key_contact() const + { + GINT _coords[] = { + (GINT)(m_point[0]*1000.0f+1.0f), + (GINT)(m_point[1]*1333.0f), + (GINT)(m_point[2]*2133.0f+3.0f)}; + GUINT _hash=0; + GUINT *_uitmp = (GUINT *)(&_coords[0]); + _hash = *_uitmp; + _uitmp++; + _hash += (*_uitmp)<<4; + _uitmp++; + _hash += (*_uitmp)<<8; + return _hash; + } + + SIMD_FORCE_INLINE void interpolate_normals( btVector3 * normals,GUINT normal_count) + { + btVector3 vec_sum(m_normal); + for(GUINT i=0;i +{ +public: + gim_contact_array():gim_array(64) + { + } + + SIMD_FORCE_INLINE void push_contact(const btVector3 &point,const btVector3 & normal, + GREAL depth, GUINT feature1, GUINT feature2) + { + push_back_mem(); + GIM_CONTACT & newele = back(); + newele.m_point = point; + newele.m_normal = normal; + newele.m_depth = depth; + newele.m_feature1 = feature1; + newele.m_feature2 = feature2; + } + + SIMD_FORCE_INLINE void push_triangle_contacts( + const GIM_TRIANGLE_CONTACT_DATA & tricontact, + GUINT feature1,GUINT feature2) + { + for(GUINT i = 0;i +struct GIM_HASH_TABLE_NODE +{ + GUINT m_key; + T m_data; + GIM_HASH_TABLE_NODE() + { + } + + GIM_HASH_TABLE_NODE(const GIM_HASH_TABLE_NODE & value) + { + m_key = value.m_key; + m_data = value.m_data; + } + + GIM_HASH_TABLE_NODE(GUINT key, const T & data) + { + m_key = key; + m_data = data; + } + + bool operator <(const GIM_HASH_TABLE_NODE & other) const + { + ///inverse order, further objects are first + if(m_key < other.m_key) return true; + return false; + } + + bool operator >(const GIM_HASH_TABLE_NODE & other) const + { + ///inverse order, further objects are first + if(m_key > other.m_key) return true; + return false; + } + + bool operator ==(const GIM_HASH_TABLE_NODE & other) const + { + ///inverse order, further objects are first + if(m_key == other.m_key) return true; + return false; + } +}; + +///Macro for getting the key +class GIM_HASH_NODE_GET_KEY +{ +public: + template + inline GUINT operator()( const T& a) + { + return a.m_key; + } +}; + + + +///Macro for comparing the key and the element +class GIM_HASH_NODE_CMP_KEY_MACRO +{ +public: + template + inline int operator() ( const T& a, GUINT key) + { + return ((int)(a.m_key - key)); + } +}; + +///Macro for comparing Hash nodes +class GIM_HASH_NODE_CMP_MACRO +{ +public: + template + inline int operator() ( const T& a, const T& b ) + { + return ((int)(a.m_key - b.m_key)); + } +}; + + + + + +//! Sorting for hash table +/*! +switch automatically between quicksort and radixsort +*/ +template +void gim_sort_hash_node_array(T * array, GUINT array_count) +{ + if(array_count + +
      +
    • if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes. +When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable. +
    • If node_size != 0, then this container becomes a hash table for ever +
    + +*/ +template +class gim_hash_table +{ +protected: + typedef GIM_HASH_TABLE_NODE _node_type; + + //!The nodes + //array< _node_type, SuperAllocator<_node_type> > m_nodes; + gim_array< _node_type > m_nodes; + //SuperBufferedArray< _node_type > m_nodes; + bool m_sorted; + + /*! \defgroup HASH_TABLE_STRUCTURES + \brief + Hash table data management. The hash table has the indices to the corresponding m_nodes array + */ + //! @{ + + GUINT * m_hash_table;//!< + GUINT m_table_size;//!< + GUINT m_node_size;//!< + GUINT m_min_hash_table_size; + + + + //! Returns the cell index + inline GUINT _find_cell(GUINT hashkey) + { + _node_type * nodesptr = m_nodes.pointer(); + GUINT start_index = (hashkey%m_table_size)*m_node_size; + GUINT end_index = start_index + m_node_size; + + while(start_index= m_nodes.size()) return false; + if(m_nodes[index].m_key != GIM_INVALID_HASH) + { + //Search for the avaliable cell in buffer + GUINT cell_index = _find_cell(m_nodes[index].m_key); + + btAssert(cell_index!=GIM_INVALID_HASH); + btAssert(m_hash_table[cell_index]==index); + + m_hash_table[cell_index] = GIM_INVALID_HASH; + } + + return this->_erase_unsorted(index); + } + + //! erase by key in hash table + inline bool _erase_hash_table(GUINT hashkey) + { + if(hashkey == GIM_INVALID_HASH) return false; + + //Search for the avaliable cell in buffer + GUINT cell_index = _find_cell(hashkey); + if(cell_index ==GIM_INVALID_HASH) return false; + + GUINT index = m_hash_table[cell_index]; + m_hash_table[cell_index] = GIM_INVALID_HASH; + + return this->_erase_unsorted(index); + } + + + + //! insert an element in hash table + /*! + If the element exists, this won't insert the element + \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted + If so, the element has been inserted at the last position of the array. + */ + inline GUINT _insert_hash_table(GUINT hashkey, const T & value) + { + if(hashkey==GIM_INVALID_HASH) + { + //Insert anyway + _insert_unsorted(hashkey,value); + return GIM_INVALID_HASH; + } + + GUINT cell_index = _assign_hash_table_cell(hashkey); + + GUINT value_key = m_hash_table[cell_index]; + + if(value_key!= GIM_INVALID_HASH) return value_key;// Not overrited + + m_hash_table[cell_index] = m_nodes.size(); + + _insert_unsorted(hashkey,value); + return GIM_INVALID_HASH; + } + + //! insert an element in hash table. + /*! + If the element exists, this replaces the element. + \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted + If so, the element has been inserted at the last position of the array. + */ + inline GUINT _insert_hash_table_replace(GUINT hashkey, const T & value) + { + if(hashkey==GIM_INVALID_HASH) + { + //Insert anyway + _insert_unsorted(hashkey,value); + return GIM_INVALID_HASH; + } + + GUINT cell_index = _assign_hash_table_cell(hashkey); + + GUINT value_key = m_hash_table[cell_index]; + + if(value_key!= GIM_INVALID_HASH) + {//replaces the existing + m_nodes[value_key] = _node_type(hashkey,value); + return value_key;// index of the replaced element + } + + m_hash_table[cell_index] = m_nodes.size(); + + _insert_unsorted(hashkey,value); + return GIM_INVALID_HASH; + + } + + //! @} + + /*! \defgroup SORTED_ARRAY_STRUCTURES + \brief + Sorted array data management. The hash table has the indices to the corresponding m_nodes array + */ + //! @{ + inline bool _erase_sorted(GUINT index) + { + if(index>=(GUINT)m_nodes.size()) return false; + m_nodes.erase_sorted(index); + if(m_nodes.size()<2) m_sorted = false; + return true; + } + + //! faster, but unsorted + inline bool _erase_unsorted(GUINT index) + { + if(index>=m_nodes.size()) return false; + + GUINT lastindex = m_nodes.size()-1; + if(indexcheck_for_switching_to_hashtable(); + } + + //! Insert an element in an ordered array + inline GUINT _insert_sorted(GUINT hashkey, const T & value) + { + if(hashkey==GIM_INVALID_HASH || size()==0) + { + m_nodes.push_back(_node_type(hashkey,value)); + return GIM_INVALID_HASH; + } + //Insert at last position + //Sort element + + + GUINT result_ind=0; + GUINT last_index = m_nodes.size()-1; + _node_type * ptr = m_nodes.pointer(); + + bool found = gim_binary_search_ex( + ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO()); + + + //Insert before found index + if(found) + { + return result_ind; + } + else + { + _insert_in_pos(hashkey, value, result_ind); + } + return GIM_INVALID_HASH; + } + + inline GUINT _insert_sorted_replace(GUINT hashkey, const T & value) + { + if(hashkey==GIM_INVALID_HASH || size()==0) + { + m_nodes.push_back(_node_type(hashkey,value)); + return GIM_INVALID_HASH; + } + //Insert at last position + //Sort element + GUINT result_ind; + GUINT last_index = m_nodes.size()-1; + _node_type * ptr = m_nodes.pointer(); + + bool found = gim_binary_search_ex( + ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO()); + + //Insert before found index + if(found) + { + m_nodes[result_ind] = _node_type(hashkey,value); + } + else + { + _insert_in_pos(hashkey, value, result_ind); + } + return result_ind; + } + + //! Fast insertion in m_nodes array + inline GUINT _insert_unsorted(GUINT hashkey, const T & value) + { + m_nodes.push_back(_node_type(hashkey,value)); + m_sorted = false; + return GIM_INVALID_HASH; + } + + //! @} + + +public: + + /*! +
  6. if node_size = 0, then this container becomes a simple sorted array allocator. reserve_size is used for reserve memory in m_nodes. + When the array size reaches the size equivalent to 'min_hash_table_size', then it becomes a hash table by calling check_for_switching_to_hashtable. +
  7. If node_size != 0, then this container becomes a hash table for ever + + */ + gim_hash_table(GUINT reserve_size = GIM_DEFAULT_HASH_TABLE_SIZE, + GUINT node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE, + GUINT min_hash_table_size = GIM_INVALID_HASH) + { + m_hash_table = NULL; + m_table_size = 0; + m_sorted = false; + m_node_size = node_size; + m_min_hash_table_size = min_hash_table_size; + + if(m_node_size!=0) + { + if(reserve_size!=0) + { + m_nodes.reserve(reserve_size); + _reserve_table_memory(reserve_size); + _invalidate_keys(); + } + else + { + m_nodes.reserve(GIM_DEFAULT_HASH_TABLE_SIZE); + _reserve_table_memory(GIM_DEFAULT_HASH_TABLE_SIZE); + _invalidate_keys(); + } + } + else if(reserve_size!=0) + { + m_nodes.reserve(reserve_size); + } + + } + + ~gim_hash_table() + { + _destroy(); + } + + inline bool is_hash_table() + { + if(m_hash_table) return true; + return false; + } + + inline bool is_sorted() + { + if(size()<2) return true; + return m_sorted; + } + + bool sort() + { + if(is_sorted()) return true; + if(m_nodes.size()<2) return false; + + + _node_type * ptr = m_nodes.pointer(); + GUINT siz = m_nodes.size(); + gim_sort_hash_node_array(ptr,siz); + m_sorted=true; + + + + if(m_hash_table) + { + _rehash(); + } + return true; + } + + bool switch_to_hashtable() + { + if(m_hash_table) return false; + if(m_node_size==0) m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE; + if(m_nodes.size()m_hash_table) return true; + + if(!(m_nodes.size()< m_min_hash_table_size)) + { + if(m_node_size == 0) + { + m_node_size = GIM_DEFAULT_HASH_TABLE_NODE_SIZE; + } + + _resize_table(m_nodes.size()+1); + return true; + } + return false; + } + + inline void set_sorted(bool value) + { + m_sorted = value; + } + + //! Retrieves the amount of keys. + inline GUINT size() const + { + return m_nodes.size(); + } + + //! Retrieves the hash key. + inline GUINT get_key(GUINT index) const + { + return m_nodes[index].m_key; + } + + //! Retrieves the value by index + /*! + */ + inline T * get_value_by_index(GUINT index) + { + return &m_nodes[index].m_data; + } + + inline const T& operator[](GUINT index) const + { + return m_nodes[index].m_data; + } + + inline T& operator[](GUINT index) + { + return m_nodes[index].m_data; + } + + //! Finds the index of the element with the key + /*! + \return the index in the array of the existing element,or GIM_INVALID_HASH if the element has been inserted + If so, the element has been inserted at the last position of the array. + */ + inline GUINT find(GUINT hashkey) + { + if(m_hash_table) + { + GUINT cell_index = _find_cell(hashkey); + if(cell_index==GIM_INVALID_HASH) return GIM_INVALID_HASH; + return m_hash_table[cell_index]; + } + GUINT last_index = m_nodes.size(); + if(last_index<2) + { + if(last_index==0) return GIM_INVALID_HASH; + if(m_nodes[0].m_key == hashkey) return 0; + return GIM_INVALID_HASH; + } + else if(m_sorted) + { + //Binary search + GUINT result_ind = 0; + last_index--; + _node_type * ptr = m_nodes.pointer(); + + bool found = gim_binary_search_ex(ptr,0,last_index,result_ind,hashkey,GIM_HASH_NODE_CMP_KEY_MACRO()); + + + if(found) return result_ind; + } + return GIM_INVALID_HASH; + } + + //! Retrieves the value associated with the index + /*! + \return the found element, or null + */ + inline T * get_value(GUINT hashkey) + { + GUINT index = find(hashkey); + if(index == GIM_INVALID_HASH) return NULL; + return &m_nodes[index].m_data; + } + + + /*! + */ + inline bool erase_by_index(GUINT index) + { + if(index > m_nodes.size()) return false; + + if(m_hash_table == NULL) + { + if(is_sorted()) + { + return this->_erase_sorted(index); + } + else + { + return this->_erase_unsorted(index); + } + } + else + { + return this->_erase_by_index_hash_table(index); + } + return false; + } + + + + inline bool erase_by_index_unsorted(GUINT index) + { + if(index > m_nodes.size()) return false; + + if(m_hash_table == NULL) + { + return this->_erase_unsorted(index); + } + else + { + return this->_erase_by_index_hash_table(index); + } + return false; + } + + + + /*! + + */ + inline bool erase_by_key(GUINT hashkey) + { + if(size()==0) return false; + + if(m_hash_table) + { + return this->_erase_hash_table(hashkey); + } + //Binary search + + if(is_sorted()==false) return false; + + GUINT result_ind = find(hashkey); + if(result_ind!= GIM_INVALID_HASH) + { + return this->_erase_sorted(result_ind); + } + return false; + } + + void clear() + { + m_nodes.clear(); + + if(m_hash_table==NULL) return; + GUINT datasize = m_table_size*m_node_size; + //Initialize the hashkeys. + GUINT i; + for(i=0;i_insert_hash_table(hashkey,element); + } + if(this->is_sorted()) + { + return this->_insert_sorted(hashkey,element); + } + return this->_insert_unsorted(hashkey,element); + } + + //! Insert an element into the hash, and could overrite an existing object with the same hash. + /*! + \return If GIM_INVALID_HASH, the object has been inserted succesfully. Else it returns the position + of the replaced element. + */ + inline GUINT insert_override(GUINT hashkey, const T & element) + { + if(m_hash_table) + { + return this->_insert_hash_table_replace(hashkey,element); + } + if(this->is_sorted()) + { + return this->_insert_sorted_replace(hashkey,element); + } + this->_insert_unsorted(hashkey,element); + return m_nodes.size(); + } + + + + //! Insert an element into the hash,But if this container is a sorted array, this inserts it unsorted + /*! + */ + inline GUINT insert_unsorted(GUINT hashkey,const T & element) + { + if(m_hash_table) + { + return this->_insert_hash_table(hashkey,element); + } + return this->_insert_unsorted(hashkey,element); + } + + +}; + +//! @} + + + +#endif // GIM_CONTAINERS_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_linear_math.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_linear_math.h new file mode 100644 index 00000000000..7bfd50409db --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_linear_math.h @@ -0,0 +1,1584 @@ +#ifndef GIM_LINEAR_H_INCLUDED +#define GIM_LINEAR_H_INCLUDED + +/*! \file gim_linear_math.h +*\author Francisco León Nájera +Type Independant Vector and matrix operations. +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + + +#include "gim_math.h" +#include "gim_geom_types.h" + + + +/*! \defgroup VECTOR_OPERATIONS +T +Operations for vectors : vec2f,vec3f and vec4f +*/ +//! @{ + +//! Zero out a 2D vector +#define VEC_ZERO_2(a) \ +{ \ + (a)[0] = (a)[1] = 0.0f; \ +}\ + + +//! Zero out a 3D vector +#define VEC_ZERO(a) \ +{ \ + (a)[0] = (a)[1] = (a)[2] = 0.0f; \ +}\ + + +/// Zero out a 4D vector +#define VEC_ZERO_4(a) \ +{ \ + (a)[0] = (a)[1] = (a)[2] = (a)[3] = 0.0f; \ +}\ + + +/// Vector copy +#define VEC_COPY_2(b,a) \ +{ \ + (b)[0] = (a)[0]; \ + (b)[1] = (a)[1]; \ +}\ + + +/// Copy 3D vector +#define VEC_COPY(b,a) \ +{ \ + (b)[0] = (a)[0]; \ + (b)[1] = (a)[1]; \ + (b)[2] = (a)[2]; \ +}\ + + +/// Copy 4D vector +#define VEC_COPY_4(b,a) \ +{ \ + (b)[0] = (a)[0]; \ + (b)[1] = (a)[1]; \ + (b)[2] = (a)[2]; \ + (b)[3] = (a)[3]; \ +}\ + +/// VECTOR SWAP +#define VEC_SWAP(b,a) \ +{ \ + GIM_SWAP_NUMBERS((b)[0],(a)[0]);\ + GIM_SWAP_NUMBERS((b)[1],(a)[1]);\ + GIM_SWAP_NUMBERS((b)[2],(a)[2]);\ +}\ + +/// Vector difference +#define VEC_DIFF_2(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] - (v1)[0]; \ + (v21)[1] = (v2)[1] - (v1)[1]; \ +}\ + + +/// Vector difference +#define VEC_DIFF(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] - (v1)[0]; \ + (v21)[1] = (v2)[1] - (v1)[1]; \ + (v21)[2] = (v2)[2] - (v1)[2]; \ +}\ + + +/// Vector difference +#define VEC_DIFF_4(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] - (v1)[0]; \ + (v21)[1] = (v2)[1] - (v1)[1]; \ + (v21)[2] = (v2)[2] - (v1)[2]; \ + (v21)[3] = (v2)[3] - (v1)[3]; \ +}\ + + +/// Vector sum +#define VEC_SUM_2(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] + (v1)[0]; \ + (v21)[1] = (v2)[1] + (v1)[1]; \ +}\ + + +/// Vector sum +#define VEC_SUM(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] + (v1)[0]; \ + (v21)[1] = (v2)[1] + (v1)[1]; \ + (v21)[2] = (v2)[2] + (v1)[2]; \ +}\ + + +/// Vector sum +#define VEC_SUM_4(v21,v2,v1) \ +{ \ + (v21)[0] = (v2)[0] + (v1)[0]; \ + (v21)[1] = (v2)[1] + (v1)[1]; \ + (v21)[2] = (v2)[2] + (v1)[2]; \ + (v21)[3] = (v2)[3] + (v1)[3]; \ +}\ + + +/// scalar times vector +#define VEC_SCALE_2(c,a,b) \ +{ \ + (c)[0] = (a)*(b)[0]; \ + (c)[1] = (a)*(b)[1]; \ +}\ + + +/// scalar times vector +#define VEC_SCALE(c,a,b) \ +{ \ + (c)[0] = (a)*(b)[0]; \ + (c)[1] = (a)*(b)[1]; \ + (c)[2] = (a)*(b)[2]; \ +}\ + + +/// scalar times vector +#define VEC_SCALE_4(c,a,b) \ +{ \ + (c)[0] = (a)*(b)[0]; \ + (c)[1] = (a)*(b)[1]; \ + (c)[2] = (a)*(b)[2]; \ + (c)[3] = (a)*(b)[3]; \ +}\ + + +/// accumulate scaled vector +#define VEC_ACCUM_2(c,a,b) \ +{ \ + (c)[0] += (a)*(b)[0]; \ + (c)[1] += (a)*(b)[1]; \ +}\ + + +/// accumulate scaled vector +#define VEC_ACCUM(c,a,b) \ +{ \ + (c)[0] += (a)*(b)[0]; \ + (c)[1] += (a)*(b)[1]; \ + (c)[2] += (a)*(b)[2]; \ +}\ + + +/// accumulate scaled vector +#define VEC_ACCUM_4(c,a,b) \ +{ \ + (c)[0] += (a)*(b)[0]; \ + (c)[1] += (a)*(b)[1]; \ + (c)[2] += (a)*(b)[2]; \ + (c)[3] += (a)*(b)[3]; \ +}\ + + +/// Vector dot product +#define VEC_DOT_2(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1]) + + +/// Vector dot product +#define VEC_DOT(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2]) + +/// Vector dot product +#define VEC_DOT_4(a,b) ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] + (a)[3]*(b)[3]) + +/// vector impact parameter (squared) +#define VEC_IMPACT_SQ(bsq,direction,position) {\ + GREAL _llel_ = VEC_DOT(direction, position);\ + bsq = VEC_DOT(position, position) - _llel_*_llel_;\ +}\ + + +/// vector impact parameter +#define VEC_IMPACT(bsq,direction,position) {\ + VEC_IMPACT_SQ(bsq,direction,position); \ + GIM_SQRT(bsq,bsq); \ +}\ + +/// Vector length +#define VEC_LENGTH_2(a,l)\ +{\ + GREAL _pp = VEC_DOT_2(a,a);\ + GIM_SQRT(_pp,l);\ +}\ + + +/// Vector length +#define VEC_LENGTH(a,l)\ +{\ + GREAL _pp = VEC_DOT(a,a);\ + GIM_SQRT(_pp,l);\ +}\ + + +/// Vector length +#define VEC_LENGTH_4(a,l)\ +{\ + GREAL _pp = VEC_DOT_4(a,a);\ + GIM_SQRT(_pp,l);\ +}\ + +/// Vector inv length +#define VEC_INV_LENGTH_2(a,l)\ +{\ + GREAL _pp = VEC_DOT_2(a,a);\ + GIM_INV_SQRT(_pp,l);\ +}\ + + +/// Vector inv length +#define VEC_INV_LENGTH(a,l)\ +{\ + GREAL _pp = VEC_DOT(a,a);\ + GIM_INV_SQRT(_pp,l);\ +}\ + + +/// Vector inv length +#define VEC_INV_LENGTH_4(a,l)\ +{\ + GREAL _pp = VEC_DOT_4(a,a);\ + GIM_INV_SQRT(_pp,l);\ +}\ + + + +/// distance between two points +#define VEC_DISTANCE(_len,_va,_vb) {\ + vec3f _tmp_; \ + VEC_DIFF(_tmp_, _vb, _va); \ + VEC_LENGTH(_tmp_,_len); \ +}\ + + +/// Vector length +#define VEC_CONJUGATE_LENGTH(a,l)\ +{\ + GREAL _pp = 1.0 - a[0]*a[0] - a[1]*a[1] - a[2]*a[2];\ + GIM_SQRT(_pp,l);\ +}\ + + +/// Vector length +#define VEC_NORMALIZE(a) { \ + GREAL len;\ + VEC_INV_LENGTH(a,len); \ + if(lenA[1]?(A[0]>A[2]?0:2):(A[1]>A[2]?1:2);\ +}\ + +//! Finds the 2 smallest cartesian coordinates from a vector +#define VEC_MINOR_AXES(vec, i0, i1)\ +{\ + VEC_MAYOR_COORD(vec,i0);\ + i0 = (i0+1)%3;\ + i1 = (i0+1)%3;\ +}\ + + + + +#define VEC_EQUAL(v1,v2) (v1[0]==v2[0]&&v1[1]==v2[1]&&v1[2]==v2[2]) + +#define VEC_NEAR_EQUAL(v1,v2) (GIM_NEAR_EQUAL(v1[0],v2[0])&&GIM_NEAR_EQUAL(v1[1],v2[1])&&GIM_NEAR_EQUAL(v1[2],v2[2])) + + +/// Vector cross +#define X_AXIS_CROSS_VEC(dst,src)\ +{ \ + dst[0] = 0.0f; \ + dst[1] = -src[2]; \ + dst[2] = src[1]; \ +}\ + +#define Y_AXIS_CROSS_VEC(dst,src)\ +{ \ + dst[0] = src[2]; \ + dst[1] = 0.0f; \ + dst[2] = -src[0]; \ +}\ + +#define Z_AXIS_CROSS_VEC(dst,src)\ +{ \ + dst[0] = -src[1]; \ + dst[1] = src[0]; \ + dst[2] = 0.0f; \ +}\ + + + +//! @} + + +/*! \defgroup MATRIX_OPERATIONS +Operations for matrices : mat2f, mat3f and mat4f +*/ +//! @{ + +/// initialize matrix +#define IDENTIFY_MATRIX_3X3(m) \ +{ \ + m[0][0] = 1.0; \ + m[0][1] = 0.0; \ + m[0][2] = 0.0; \ + \ + m[1][0] = 0.0; \ + m[1][1] = 1.0; \ + m[1][2] = 0.0; \ + \ + m[2][0] = 0.0; \ + m[2][1] = 0.0; \ + m[2][2] = 1.0; \ +}\ + +/*! initialize matrix */ +#define IDENTIFY_MATRIX_4X4(m) \ +{ \ + m[0][0] = 1.0; \ + m[0][1] = 0.0; \ + m[0][2] = 0.0; \ + m[0][3] = 0.0; \ + \ + m[1][0] = 0.0; \ + m[1][1] = 1.0; \ + m[1][2] = 0.0; \ + m[1][3] = 0.0; \ + \ + m[2][0] = 0.0; \ + m[2][1] = 0.0; \ + m[2][2] = 1.0; \ + m[2][3] = 0.0; \ + \ + m[3][0] = 0.0; \ + m[3][1] = 0.0; \ + m[3][2] = 0.0; \ + m[3][3] = 1.0; \ +}\ + +/*! initialize matrix */ +#define ZERO_MATRIX_4X4(m) \ +{ \ + m[0][0] = 0.0; \ + m[0][1] = 0.0; \ + m[0][2] = 0.0; \ + m[0][3] = 0.0; \ + \ + m[1][0] = 0.0; \ + m[1][1] = 0.0; \ + m[1][2] = 0.0; \ + m[1][3] = 0.0; \ + \ + m[2][0] = 0.0; \ + m[2][1] = 0.0; \ + m[2][2] = 0.0; \ + m[2][3] = 0.0; \ + \ + m[3][0] = 0.0; \ + m[3][1] = 0.0; \ + m[3][2] = 0.0; \ + m[3][3] = 0.0; \ +}\ + +/*! matrix rotation X */ +#define ROTX_CS(m,cosine,sine) \ +{ \ + /* rotation about the x-axis */ \ + \ + m[0][0] = 1.0; \ + m[0][1] = 0.0; \ + m[0][2] = 0.0; \ + m[0][3] = 0.0; \ + \ + m[1][0] = 0.0; \ + m[1][1] = (cosine); \ + m[1][2] = (sine); \ + m[1][3] = 0.0; \ + \ + m[2][0] = 0.0; \ + m[2][1] = -(sine); \ + m[2][2] = (cosine); \ + m[2][3] = 0.0; \ + \ + m[3][0] = 0.0; \ + m[3][1] = 0.0; \ + m[3][2] = 0.0; \ + m[3][3] = 1.0; \ +}\ + +/*! matrix rotation Y */ +#define ROTY_CS(m,cosine,sine) \ +{ \ + /* rotation about the y-axis */ \ + \ + m[0][0] = (cosine); \ + m[0][1] = 0.0; \ + m[0][2] = -(sine); \ + m[0][3] = 0.0; \ + \ + m[1][0] = 0.0; \ + m[1][1] = 1.0; \ + m[1][2] = 0.0; \ + m[1][3] = 0.0; \ + \ + m[2][0] = (sine); \ + m[2][1] = 0.0; \ + m[2][2] = (cosine); \ + m[2][3] = 0.0; \ + \ + m[3][0] = 0.0; \ + m[3][1] = 0.0; \ + m[3][2] = 0.0; \ + m[3][3] = 1.0; \ +}\ + +/*! matrix rotation Z */ +#define ROTZ_CS(m,cosine,sine) \ +{ \ + /* rotation about the z-axis */ \ + \ + m[0][0] = (cosine); \ + m[0][1] = (sine); \ + m[0][2] = 0.0; \ + m[0][3] = 0.0; \ + \ + m[1][0] = -(sine); \ + m[1][1] = (cosine); \ + m[1][2] = 0.0; \ + m[1][3] = 0.0; \ + \ + m[2][0] = 0.0; \ + m[2][1] = 0.0; \ + m[2][2] = 1.0; \ + m[2][3] = 0.0; \ + \ + m[3][0] = 0.0; \ + m[3][1] = 0.0; \ + m[3][2] = 0.0; \ + m[3][3] = 1.0; \ +}\ + +/*! matrix copy */ +#define COPY_MATRIX_2X2(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[0][1]; \ + \ + b[1][0] = a[1][0]; \ + b[1][1] = a[1][1]; \ + \ +}\ + + +/*! matrix copy */ +#define COPY_MATRIX_2X3(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[0][1]; \ + b[0][2] = a[0][2]; \ + \ + b[1][0] = a[1][0]; \ + b[1][1] = a[1][1]; \ + b[1][2] = a[1][2]; \ +}\ + + +/*! matrix copy */ +#define COPY_MATRIX_3X3(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[0][1]; \ + b[0][2] = a[0][2]; \ + \ + b[1][0] = a[1][0]; \ + b[1][1] = a[1][1]; \ + b[1][2] = a[1][2]; \ + \ + b[2][0] = a[2][0]; \ + b[2][1] = a[2][1]; \ + b[2][2] = a[2][2]; \ +}\ + + +/*! matrix copy */ +#define COPY_MATRIX_4X4(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[0][1]; \ + b[0][2] = a[0][2]; \ + b[0][3] = a[0][3]; \ + \ + b[1][0] = a[1][0]; \ + b[1][1] = a[1][1]; \ + b[1][2] = a[1][2]; \ + b[1][3] = a[1][3]; \ + \ + b[2][0] = a[2][0]; \ + b[2][1] = a[2][1]; \ + b[2][2] = a[2][2]; \ + b[2][3] = a[2][3]; \ + \ + b[3][0] = a[3][0]; \ + b[3][1] = a[3][1]; \ + b[3][2] = a[3][2]; \ + b[3][3] = a[3][3]; \ +}\ + + +/*! matrix transpose */ +#define TRANSPOSE_MATRIX_2X2(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[1][0]; \ + \ + b[1][0] = a[0][1]; \ + b[1][1] = a[1][1]; \ +}\ + + +/*! matrix transpose */ +#define TRANSPOSE_MATRIX_3X3(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[1][0]; \ + b[0][2] = a[2][0]; \ + \ + b[1][0] = a[0][1]; \ + b[1][1] = a[1][1]; \ + b[1][2] = a[2][1]; \ + \ + b[2][0] = a[0][2]; \ + b[2][1] = a[1][2]; \ + b[2][2] = a[2][2]; \ +}\ + + +/*! matrix transpose */ +#define TRANSPOSE_MATRIX_4X4(b,a) \ +{ \ + b[0][0] = a[0][0]; \ + b[0][1] = a[1][0]; \ + b[0][2] = a[2][0]; \ + b[0][3] = a[3][0]; \ + \ + b[1][0] = a[0][1]; \ + b[1][1] = a[1][1]; \ + b[1][2] = a[2][1]; \ + b[1][3] = a[3][1]; \ + \ + b[2][0] = a[0][2]; \ + b[2][1] = a[1][2]; \ + b[2][2] = a[2][2]; \ + b[2][3] = a[3][2]; \ + \ + b[3][0] = a[0][3]; \ + b[3][1] = a[1][3]; \ + b[3][2] = a[2][3]; \ + b[3][3] = a[3][3]; \ +}\ + + +/*! multiply matrix by scalar */ +#define SCALE_MATRIX_2X2(b,s,a) \ +{ \ + b[0][0] = (s) * a[0][0]; \ + b[0][1] = (s) * a[0][1]; \ + \ + b[1][0] = (s) * a[1][0]; \ + b[1][1] = (s) * a[1][1]; \ +}\ + + +/*! multiply matrix by scalar */ +#define SCALE_MATRIX_3X3(b,s,a) \ +{ \ + b[0][0] = (s) * a[0][0]; \ + b[0][1] = (s) * a[0][1]; \ + b[0][2] = (s) * a[0][2]; \ + \ + b[1][0] = (s) * a[1][0]; \ + b[1][1] = (s) * a[1][1]; \ + b[1][2] = (s) * a[1][2]; \ + \ + b[2][0] = (s) * a[2][0]; \ + b[2][1] = (s) * a[2][1]; \ + b[2][2] = (s) * a[2][2]; \ +}\ + + +/*! multiply matrix by scalar */ +#define SCALE_MATRIX_4X4(b,s,a) \ +{ \ + b[0][0] = (s) * a[0][0]; \ + b[0][1] = (s) * a[0][1]; \ + b[0][2] = (s) * a[0][2]; \ + b[0][3] = (s) * a[0][3]; \ + \ + b[1][0] = (s) * a[1][0]; \ + b[1][1] = (s) * a[1][1]; \ + b[1][2] = (s) * a[1][2]; \ + b[1][3] = (s) * a[1][3]; \ + \ + b[2][0] = (s) * a[2][0]; \ + b[2][1] = (s) * a[2][1]; \ + b[2][2] = (s) * a[2][2]; \ + b[2][3] = (s) * a[2][3]; \ + \ + b[3][0] = s * a[3][0]; \ + b[3][1] = s * a[3][1]; \ + b[3][2] = s * a[3][2]; \ + b[3][3] = s * a[3][3]; \ +}\ + + +/*! multiply matrix by scalar */ +#define SCALE_VEC_MATRIX_2X2(b,svec,a) \ +{ \ + b[0][0] = svec[0] * a[0][0]; \ + b[1][0] = svec[0] * a[1][0]; \ + \ + b[0][1] = svec[1] * a[0][1]; \ + b[1][1] = svec[1] * a[1][1]; \ +}\ + + +/*! multiply matrix by scalar. Each columns is scaled by each scalar vector component */ +#define SCALE_VEC_MATRIX_3X3(b,svec,a) \ +{ \ + b[0][0] = svec[0] * a[0][0]; \ + b[1][0] = svec[0] * a[1][0]; \ + b[2][0] = svec[0] * a[2][0]; \ + \ + b[0][1] = svec[1] * a[0][1]; \ + b[1][1] = svec[1] * a[1][1]; \ + b[2][1] = svec[1] * a[2][1]; \ + \ + b[0][2] = svec[2] * a[0][2]; \ + b[1][2] = svec[2] * a[1][2]; \ + b[2][2] = svec[2] * a[2][2]; \ +}\ + + +/*! multiply matrix by scalar */ +#define SCALE_VEC_MATRIX_4X4(b,svec,a) \ +{ \ + b[0][0] = svec[0] * a[0][0]; \ + b[1][0] = svec[0] * a[1][0]; \ + b[2][0] = svec[0] * a[2][0]; \ + b[3][0] = svec[0] * a[3][0]; \ + \ + b[0][1] = svec[1] * a[0][1]; \ + b[1][1] = svec[1] * a[1][1]; \ + b[2][1] = svec[1] * a[2][1]; \ + b[3][1] = svec[1] * a[3][1]; \ + \ + b[0][2] = svec[2] * a[0][2]; \ + b[1][2] = svec[2] * a[1][2]; \ + b[2][2] = svec[2] * a[2][2]; \ + b[3][2] = svec[2] * a[3][2]; \ + \ + b[0][3] = svec[3] * a[0][3]; \ + b[1][3] = svec[3] * a[1][3]; \ + b[2][3] = svec[3] * a[2][3]; \ + b[3][3] = svec[3] * a[3][3]; \ +}\ + + +/*! multiply matrix by scalar */ +#define ACCUM_SCALE_MATRIX_2X2(b,s,a) \ +{ \ + b[0][0] += (s) * a[0][0]; \ + b[0][1] += (s) * a[0][1]; \ + \ + b[1][0] += (s) * a[1][0]; \ + b[1][1] += (s) * a[1][1]; \ +}\ + + +/*! multiply matrix by scalar */ +#define ACCUM_SCALE_MATRIX_3X3(b,s,a) \ +{ \ + b[0][0] += (s) * a[0][0]; \ + b[0][1] += (s) * a[0][1]; \ + b[0][2] += (s) * a[0][2]; \ + \ + b[1][0] += (s) * a[1][0]; \ + b[1][1] += (s) * a[1][1]; \ + b[1][2] += (s) * a[1][2]; \ + \ + b[2][0] += (s) * a[2][0]; \ + b[2][1] += (s) * a[2][1]; \ + b[2][2] += (s) * a[2][2]; \ +}\ + + +/*! multiply matrix by scalar */ +#define ACCUM_SCALE_MATRIX_4X4(b,s,a) \ +{ \ + b[0][0] += (s) * a[0][0]; \ + b[0][1] += (s) * a[0][1]; \ + b[0][2] += (s) * a[0][2]; \ + b[0][3] += (s) * a[0][3]; \ + \ + b[1][0] += (s) * a[1][0]; \ + b[1][1] += (s) * a[1][1]; \ + b[1][2] += (s) * a[1][2]; \ + b[1][3] += (s) * a[1][3]; \ + \ + b[2][0] += (s) * a[2][0]; \ + b[2][1] += (s) * a[2][1]; \ + b[2][2] += (s) * a[2][2]; \ + b[2][3] += (s) * a[2][3]; \ + \ + b[3][0] += (s) * a[3][0]; \ + b[3][1] += (s) * a[3][1]; \ + b[3][2] += (s) * a[3][2]; \ + b[3][3] += (s) * a[3][3]; \ +}\ + +/*! matrix product */ +/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/ +#define MATRIX_PRODUCT_2X2(c,a,b) \ +{ \ + c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]; \ + c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]; \ + \ + c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]; \ + c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]; \ + \ +}\ + +/*! matrix product */ +/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/ +#define MATRIX_PRODUCT_3X3(c,a,b) \ +{ \ + c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0]; \ + c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]+a[0][2]*b[2][1]; \ + c[0][2] = a[0][0]*b[0][2]+a[0][1]*b[1][2]+a[0][2]*b[2][2]; \ + \ + c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]+a[1][2]*b[2][0]; \ + c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]+a[1][2]*b[2][1]; \ + c[1][2] = a[1][0]*b[0][2]+a[1][1]*b[1][2]+a[1][2]*b[2][2]; \ + \ + c[2][0] = a[2][0]*b[0][0]+a[2][1]*b[1][0]+a[2][2]*b[2][0]; \ + c[2][1] = a[2][0]*b[0][1]+a[2][1]*b[1][1]+a[2][2]*b[2][1]; \ + c[2][2] = a[2][0]*b[0][2]+a[2][1]*b[1][2]+a[2][2]*b[2][2]; \ +}\ + + +/*! matrix product */ +/*! c[x][y] = a[x][0]*b[0][y]+a[x][1]*b[1][y]+a[x][2]*b[2][y]+a[x][3]*b[3][y];*/ +#define MATRIX_PRODUCT_4X4(c,a,b) \ +{ \ + c[0][0] = a[0][0]*b[0][0]+a[0][1]*b[1][0]+a[0][2]*b[2][0]+a[0][3]*b[3][0];\ + c[0][1] = a[0][0]*b[0][1]+a[0][1]*b[1][1]+a[0][2]*b[2][1]+a[0][3]*b[3][1];\ + c[0][2] = a[0][0]*b[0][2]+a[0][1]*b[1][2]+a[0][2]*b[2][2]+a[0][3]*b[3][2];\ + c[0][3] = a[0][0]*b[0][3]+a[0][1]*b[1][3]+a[0][2]*b[2][3]+a[0][3]*b[3][3];\ + \ + c[1][0] = a[1][0]*b[0][0]+a[1][1]*b[1][0]+a[1][2]*b[2][0]+a[1][3]*b[3][0];\ + c[1][1] = a[1][0]*b[0][1]+a[1][1]*b[1][1]+a[1][2]*b[2][1]+a[1][3]*b[3][1];\ + c[1][2] = a[1][0]*b[0][2]+a[1][1]*b[1][2]+a[1][2]*b[2][2]+a[1][3]*b[3][2];\ + c[1][3] = a[1][0]*b[0][3]+a[1][1]*b[1][3]+a[1][2]*b[2][3]+a[1][3]*b[3][3];\ + \ + c[2][0] = a[2][0]*b[0][0]+a[2][1]*b[1][0]+a[2][2]*b[2][0]+a[2][3]*b[3][0];\ + c[2][1] = a[2][0]*b[0][1]+a[2][1]*b[1][1]+a[2][2]*b[2][1]+a[2][3]*b[3][1];\ + c[2][2] = a[2][0]*b[0][2]+a[2][1]*b[1][2]+a[2][2]*b[2][2]+a[2][3]*b[3][2];\ + c[2][3] = a[2][0]*b[0][3]+a[2][1]*b[1][3]+a[2][2]*b[2][3]+a[2][3]*b[3][3];\ + \ + c[3][0] = a[3][0]*b[0][0]+a[3][1]*b[1][0]+a[3][2]*b[2][0]+a[3][3]*b[3][0];\ + c[3][1] = a[3][0]*b[0][1]+a[3][1]*b[1][1]+a[3][2]*b[2][1]+a[3][3]*b[3][1];\ + c[3][2] = a[3][0]*b[0][2]+a[3][1]*b[1][2]+a[3][2]*b[2][2]+a[3][3]*b[3][2];\ + c[3][3] = a[3][0]*b[0][3]+a[3][1]*b[1][3]+a[3][2]*b[2][3]+a[3][3]*b[3][3];\ +}\ + + +/*! matrix times vector */ +#define MAT_DOT_VEC_2X2(p,m,v) \ +{ \ + p[0] = m[0][0]*v[0] + m[0][1]*v[1]; \ + p[1] = m[1][0]*v[0] + m[1][1]*v[1]; \ +}\ + + +/*! matrix times vector */ +#define MAT_DOT_VEC_3X3(p,m,v) \ +{ \ + p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2]; \ + p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2]; \ + p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2]; \ +}\ + + +/*! matrix times vector +v is a vec4f +*/ +#define MAT_DOT_VEC_4X4(p,m,v) \ +{ \ + p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2] + m[0][3]*v[3]; \ + p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2] + m[1][3]*v[3]; \ + p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2] + m[2][3]*v[3]; \ + p[3] = m[3][0]*v[0] + m[3][1]*v[1] + m[3][2]*v[2] + m[3][3]*v[3]; \ +}\ + +/*! matrix times vector +v is a vec3f +and m is a mat4f
    +Last column is added as the position +*/ +#define MAT_DOT_VEC_3X4(p,m,v) \ +{ \ + p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]*v[2] + m[0][3]; \ + p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]*v[2] + m[1][3]; \ + p[2] = m[2][0]*v[0] + m[2][1]*v[1] + m[2][2]*v[2] + m[2][3]; \ +}\ + + +/*! vector transpose times matrix */ +/*! p[j] = v[0]*m[0][j] + v[1]*m[1][j] + v[2]*m[2][j]; */ +#define VEC_DOT_MAT_3X3(p,v,m) \ +{ \ + p[0] = v[0]*m[0][0] + v[1]*m[1][0] + v[2]*m[2][0]; \ + p[1] = v[0]*m[0][1] + v[1]*m[1][1] + v[2]*m[2][1]; \ + p[2] = v[0]*m[0][2] + v[1]*m[1][2] + v[2]*m[2][2]; \ +}\ + + +/*! affine matrix times vector */ +/** The matrix is assumed to be an affine matrix, with last two + * entries representing a translation */ +#define MAT_DOT_VEC_2X3(p,m,v) \ +{ \ + p[0] = m[0][0]*v[0] + m[0][1]*v[1] + m[0][2]; \ + p[1] = m[1][0]*v[0] + m[1][1]*v[1] + m[1][2]; \ +}\ + +//! Transform a plane +#define MAT_TRANSFORM_PLANE_4X4(pout,m,plane)\ +{ \ + pout[0] = m[0][0]*plane[0] + m[0][1]*plane[1] + m[0][2]*plane[2];\ + pout[1] = m[1][0]*plane[0] + m[1][1]*plane[1] + m[1][2]*plane[2];\ + pout[2] = m[2][0]*plane[0] + m[2][1]*plane[1] + m[2][2]*plane[2];\ + pout[3] = m[0][3]*pout[0] + m[1][3]*pout[1] + m[2][3]*pout[2] + plane[3];\ +}\ + + + +/** inverse transpose of matrix times vector + * + * This macro computes inverse transpose of matrix m, + * and multiplies vector v into it, to yeild vector p + * + * DANGER !!! Do Not use this on normal vectors!!! + * It will leave normals the wrong length !!! + * See macro below for use on normals. + */ +#define INV_TRANSP_MAT_DOT_VEC_2X2(p,m,v) \ +{ \ + GREAL det; \ + \ + det = m[0][0]*m[1][1] - m[0][1]*m[1][0]; \ + p[0] = m[1][1]*v[0] - m[1][0]*v[1]; \ + p[1] = - m[0][1]*v[0] + m[0][0]*v[1]; \ + \ + /* if matrix not singular, and not orthonormal, then renormalize */ \ + if ((det!=1.0f) && (det != 0.0f)) { \ + det = 1.0f / det; \ + p[0] *= det; \ + p[1] *= det; \ + } \ +}\ + + +/** transform normal vector by inverse transpose of matrix + * and then renormalize the vector + * + * This macro computes inverse transpose of matrix m, + * and multiplies vector v into it, to yeild vector p + * Vector p is then normalized. + */ +#define NORM_XFORM_2X2(p,m,v) \ +{ \ + GREAL len; \ + \ + /* do nothing if off-diagonals are zero and diagonals are \ + * equal */ \ + if ((m[0][1] != 0.0) || (m[1][0] != 0.0) || (m[0][0] != m[1][1])) { \ + p[0] = m[1][1]*v[0] - m[1][0]*v[1]; \ + p[1] = - m[0][1]*v[0] + m[0][0]*v[1]; \ + \ + len = p[0]*p[0] + p[1]*p[1]; \ + GIM_INV_SQRT(len,len); \ + p[0] *= len; \ + p[1] *= len; \ + } else { \ + VEC_COPY_2 (p, v); \ + } \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define OUTER_PRODUCT_2X2(m,v,t) \ +{ \ + m[0][0] = v[0] * t[0]; \ + m[0][1] = v[0] * t[1]; \ + \ + m[1][0] = v[1] * t[0]; \ + m[1][1] = v[1] * t[1]; \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define OUTER_PRODUCT_3X3(m,v,t) \ +{ \ + m[0][0] = v[0] * t[0]; \ + m[0][1] = v[0] * t[1]; \ + m[0][2] = v[0] * t[2]; \ + \ + m[1][0] = v[1] * t[0]; \ + m[1][1] = v[1] * t[1]; \ + m[1][2] = v[1] * t[2]; \ + \ + m[2][0] = v[2] * t[0]; \ + m[2][1] = v[2] * t[1]; \ + m[2][2] = v[2] * t[2]; \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define OUTER_PRODUCT_4X4(m,v,t) \ +{ \ + m[0][0] = v[0] * t[0]; \ + m[0][1] = v[0] * t[1]; \ + m[0][2] = v[0] * t[2]; \ + m[0][3] = v[0] * t[3]; \ + \ + m[1][0] = v[1] * t[0]; \ + m[1][1] = v[1] * t[1]; \ + m[1][2] = v[1] * t[2]; \ + m[1][3] = v[1] * t[3]; \ + \ + m[2][0] = v[2] * t[0]; \ + m[2][1] = v[2] * t[1]; \ + m[2][2] = v[2] * t[2]; \ + m[2][3] = v[2] * t[3]; \ + \ + m[3][0] = v[3] * t[0]; \ + m[3][1] = v[3] * t[1]; \ + m[3][2] = v[3] * t[2]; \ + m[3][3] = v[3] * t[3]; \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define ACCUM_OUTER_PRODUCT_2X2(m,v,t) \ +{ \ + m[0][0] += v[0] * t[0]; \ + m[0][1] += v[0] * t[1]; \ + \ + m[1][0] += v[1] * t[0]; \ + m[1][1] += v[1] * t[1]; \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define ACCUM_OUTER_PRODUCT_3X3(m,v,t) \ +{ \ + m[0][0] += v[0] * t[0]; \ + m[0][1] += v[0] * t[1]; \ + m[0][2] += v[0] * t[2]; \ + \ + m[1][0] += v[1] * t[0]; \ + m[1][1] += v[1] * t[1]; \ + m[1][2] += v[1] * t[2]; \ + \ + m[2][0] += v[2] * t[0]; \ + m[2][1] += v[2] * t[1]; \ + m[2][2] += v[2] * t[2]; \ +}\ + + +/** outer product of vector times vector transpose + * + * The outer product of vector v and vector transpose t yeilds + * dyadic matrix m. + */ +#define ACCUM_OUTER_PRODUCT_4X4(m,v,t) \ +{ \ + m[0][0] += v[0] * t[0]; \ + m[0][1] += v[0] * t[1]; \ + m[0][2] += v[0] * t[2]; \ + m[0][3] += v[0] * t[3]; \ + \ + m[1][0] += v[1] * t[0]; \ + m[1][1] += v[1] * t[1]; \ + m[1][2] += v[1] * t[2]; \ + m[1][3] += v[1] * t[3]; \ + \ + m[2][0] += v[2] * t[0]; \ + m[2][1] += v[2] * t[1]; \ + m[2][2] += v[2] * t[2]; \ + m[2][3] += v[2] * t[3]; \ + \ + m[3][0] += v[3] * t[0]; \ + m[3][1] += v[3] * t[1]; \ + m[3][2] += v[3] * t[2]; \ + m[3][3] += v[3] * t[3]; \ +}\ + + +/** determinant of matrix + * + * Computes determinant of matrix m, returning d + */ +#define DETERMINANT_2X2(d,m) \ +{ \ + d = m[0][0] * m[1][1] - m[0][1] * m[1][0]; \ +}\ + + +/** determinant of matrix + * + * Computes determinant of matrix m, returning d + */ +#define DETERMINANT_3X3(d,m) \ +{ \ + d = m[0][0] * (m[1][1]*m[2][2] - m[1][2] * m[2][1]); \ + d -= m[0][1] * (m[1][0]*m[2][2] - m[1][2] * m[2][0]); \ + d += m[0][2] * (m[1][0]*m[2][1] - m[1][1] * m[2][0]); \ +}\ + + +/** i,j,th cofactor of a 4x4 matrix + * + */ +#define COFACTOR_4X4_IJ(fac,m,i,j) \ +{ \ + GUINT __ii[4], __jj[4], __k; \ + \ + for (__k=0; __k +*/ +#define INV_MAT_DOT_VEC_3X3(p,m,v) \ +{ \ + p[0] = MAT_DOT_COL(m,v,0); \ + p[1] = MAT_DOT_COL(m,v,1); \ + p[2] = MAT_DOT_COL(m,v,2); \ +}\ + + +//! @} + +#endif // GIM_VECTOR_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_math.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_math.h new file mode 100644 index 00000000000..a30180f2810 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_math.h @@ -0,0 +1,181 @@ +#ifndef GIM_MATH_H_INCLUDED +#define GIM_MATH_H_INCLUDED +/*! \file gim_math.h +\author Francisco León Nájera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "LinearMath/btScalar.h" + + +/*! \defgroup BASIC_TYPES +Basic types and constants +Conventions: +Types starting with G +Constants starting with G_ +*/ +//! @{ + +#define GREAL btScalar +#define GREAL2 double +#define GINT int +#define GUINT unsigned int +#define GSHORT short +#define GUSHORT unsigned short +#define GINT64 long long +#define GUINT64 unsigned long long + +//! @} + +/*! \defgroup BASIC_CONSTANTS +Basic constants +Conventions: +Types starting with G +Constants starting with G_ +*/ +//! @{ + +#define G_PI 3.14159265358979f +#define G_HALF_PI 1.5707963f +//267948966 +#define G_TWO_PI 6.28318530f +//71795864 +#define G_ROOT3 1.73205f +#define G_ROOT2 1.41421f +#define G_UINT_INFINITY 0xffffffff //!< A very very high value +#define G_REAL_INFINITY FLT_MAX +#define G_SIGN_BITMASK 0x80000000 +#define G_EPSILON SIMD_EPSILON +//! @} + + +/*! \defgroup SCALAR_TYPES +\brief +Precision type constants +*/ +//! @{ +enum GIM_SCALAR_TYPES +{ + G_STYPE_REAL =0, + G_STYPE_REAL2, + G_STYPE_SHORT, + G_STYPE_USHORT, + G_STYPE_INT, + G_STYPE_UINT, + G_STYPE_INT64, + G_STYPE_UINT64 +}; +//! @} + +/*! \defgroup MATH_FUNCTIONS +mathematical functions +*/ +//! @{ + +#define G_DEGTORAD(X) ((X)*3.1415926f/180.0f) +#define G_RADTODEG(X) ((X)*180.0f/3.1415926f) + +//! Integer representation of a floating-point value. +#define GIM_IR(x) ((GUINT&)(x)) + +//! Signed integer representation of a floating-point value. +#define GIM_SIR(x) ((GINT&)(x)) + +//! Absolute integer representation of a floating-point value +#define GIM_AIR(x) (GIM_IR(x)&0x7fffffff) + +//! Floating-point representation of an integer value. +#define GIM_FR(x) ((GREAL&)(x)) + +#define GIM_MAX(a,b) (ab?b:a) + +#define GIM_MAX3(a,b,c) GIM_MAX(a,GIM_MAX(b,c)) +#define GIM_MIN3(a,b,c) GIM_MIN(a,GIM_MIN(b,c)) + +#define GIM_IS_ZERO(value) (value < G_EPSILON && value > -G_EPSILON) + +#define GIM_IS_NEGATIVE(value) (value <= -G_EPSILON) + +#define GIM_IS_POSISITVE(value) (value >= G_EPSILON) + +#define GIM_NEAR_EQUAL(v1,v2) GIM_IS_ZERO((v1-v2)) + +///returns a clamped number +#define GIM_CLAMP(number,minval,maxval) (numbermaxval?maxval:number)) + +#define GIM_GREATER(x, y) fabsf(x) > (y) + +///Swap numbers +#define GIM_SWAP_NUMBERS(a,b){ \ + a = a+b; \ + b = a-b; \ + a = a-b; \ +}\ + +#define GIM_INV_SQRT(va,isva)\ +{\ + if(va<=0.0000001f)\ + {\ + isva = G_REAL_INFINITY;\ + }\ + else\ + {\ + GREAL _x = va * 0.5f;\ + GUINT _y = 0x5f3759df - ( GIM_IR(va) >> 1);\ + isva = GIM_FR(_y);\ + isva = isva * ( 1.5f - ( _x * isva * isva ) );\ + }\ +}\ + +#define GIM_SQRT(va,sva)\ +{\ + GIM_INV_SQRT(va,sva);\ + sva = 1.0f/sva;\ +}\ + +//! Computes 1.0f / sqrtf(x). Comes from Quake3. See http://www.magic-software.com/3DGEDInvSqrt.html +inline GREAL gim_inv_sqrt(GREAL f) +{ + GREAL r; + GIM_INV_SQRT(f,r); + return r; +} + +inline GREAL gim_sqrt(GREAL f) +{ + GREAL r; + GIM_SQRT(f,r); + return r; +} + +//! @} + +#endif // GIM_MATH_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_memory.cpp b/extern/bullet2/src/BulletCollision/Gimpact/gim_memory.cpp new file mode 100644 index 00000000000..1636eb7867c --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_memory.cpp @@ -0,0 +1,135 @@ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + + +#include "gim_memory.h" +#include "stdlib.h" + +#ifdef GIM_SIMD_MEMORY +#include "LinearMath/btAlignedAllocator.h" +#endif + +static gim_alloc_function *g_allocfn = 0; +static gim_alloca_function *g_allocafn = 0; +static gim_realloc_function *g_reallocfn = 0; +static gim_free_function *g_freefn = 0; + +void gim_set_alloc_handler (gim_alloc_function *fn) +{ + g_allocfn = fn; +} + +void gim_set_alloca_handler (gim_alloca_function *fn) +{ + g_allocafn = fn; +} + +void gim_set_realloc_handler (gim_realloc_function *fn) +{ + g_reallocfn = fn; +} + +void gim_set_free_handler (gim_free_function *fn) +{ + g_freefn = fn; +} + +gim_alloc_function *gim_get_alloc_handler() +{ + return g_allocfn; +} + +gim_alloca_function *gim_get_alloca_handler() +{ + return g_allocafn; +} + + +gim_realloc_function *gim_get_realloc_handler () +{ + return g_reallocfn; +} + + +gim_free_function *gim_get_free_handler () +{ + return g_freefn; +} + + +void * gim_alloc(size_t size) +{ + void * ptr; + if (g_allocfn) + { + ptr = g_allocfn(size); + } + else + { +#ifdef GIM_SIMD_MEMORY + ptr = btAlignedAlloc(size,16); +#else + ptr = malloc(size); +#endif + } + return ptr; +} + +void * gim_alloca(size_t size) +{ + if (g_allocafn) return g_allocafn(size); else return gim_alloc(size); +} + + +void * gim_realloc(void *ptr, size_t oldsize, size_t newsize) +{ + void * newptr = gim_alloc(newsize); + size_t copysize = oldsize + +//#define PREFETCH 1 +//! \defgroup PREFETCH +//! @{ +#ifdef PREFETCH +#include // for prefetch +#define pfval 64 +#define pfval2 128 +//! Prefetch 64 +#define pf(_x,_i) _mm_prefetch((void *)(_x + _i + pfval), 0) +//! Prefetch 128 +#define pf2(_x,_i) _mm_prefetch((void *)(_x + _i + pfval2), 0) +#else +//! Prefetch 64 +#define pf(_x,_i) +//! Prefetch 128 +#define pf2(_x,_i) +#endif +//! @} + +/*! \defgroup ARRAY_UTILITIES +\brief +Functions for manip packed arrays of numbers +*/ +//! @{ +#define GIM_COPY_ARRAYS(dest_array,source_array,element_count)\ +{\ + for (GUINT _i_=0;_i_=SIMD_T_SIZE) + { + *(ui_dst_ptr++) = *(ui_src_ptr++); + copysize-=SIMD_T_SIZE; + } + if(copysize==0) return; +*/ + + char * c_src_ptr = (char *)src; + char * c_dst_ptr = (char *)dst; + while(copysize>0) + { + *(c_dst_ptr++) = *(c_src_ptr++); + copysize--; + } + return; +#else + memcpy(dst,src,copysize); +#endif +} + + + +template +inline void gim_swap_elements(T* _array,size_t _i,size_t _j) +{ + T _e_tmp_ = _array[_i]; + _array[_i] = _array[_j]; + _array[_j] = _e_tmp_; +} + + +template +inline void gim_swap_elements_memcpy(T* _array,size_t _i,size_t _j) +{ + char _e_tmp_[sizeof(T)]; + gim_simd_memcpy(_e_tmp_,&_array[_i],sizeof(T)); + gim_simd_memcpy(&_array[_i],&_array[_j],sizeof(T)); + gim_simd_memcpy(&_array[_j],_e_tmp_,sizeof(T)); +} + +template +inline void gim_swap_elements_ptr(char * _array,size_t _i,size_t _j) +{ + char _e_tmp_[SIZE]; + _i*=SIZE; + _j*=SIZE; + gim_simd_memcpy(_e_tmp_,_array+_i,SIZE); + gim_simd_memcpy(_array+_i,_array+_j,SIZE); + gim_simd_memcpy(_array+_j,_e_tmp_,SIZE); +} + +#endif // GIM_MEMORY_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_radixsort.h b/extern/bullet2/src/BulletCollision/Gimpact/gim_radixsort.h new file mode 100644 index 00000000000..b917d57bd94 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_radixsort.h @@ -0,0 +1,410 @@ +#ifndef GIM_RADIXSORT_H_INCLUDED +#define GIM_RADIXSORT_H_INCLUDED +/*! \file gim_radixsort.h +\author Francisco León Nájera. +Based on the work of Michael Herf : "fast floating-point radix sort" +Avaliable on http://www.stereopsis.com/radix.html +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "gim_memory.h" + +/*! \defgroup SORTING +\brief +Macros for sorting. +*/ + +//! Prototype for comparators +class less_comparator +{ + public: + + template + inline int operator() ( const T& a, const Z& b ) + { + return ( ab?1:0)); + } +}; + +//! Prototype for comparators +class integer_comparator +{ + public: + + template + inline int operator() ( const T& a, const T& b ) + { + return (int)(a-b); + } +}; + +//!Prototype for getting the integer representation of an object +class uint_key_func +{ +public: + template + inline GUINT operator()( const T& a) + { + return (GUINT)a; + } +}; + + +//!Prototype for copying elements +class copy_elements_func +{ +public: + template + inline void operator()(T& a,T& b) + { + a = b; + } +}; + +//!Prototype for copying elements +class memcopy_elements_func +{ +public: + template + inline void operator()(T& a,T& b) + { + gim_simd_memcpy(&a,&b,sizeof(T)); + } +}; + + +//! @{ +struct GIM_RSORT_TOKEN +{ + GUINT m_key; + GUINT m_value; + GIM_RSORT_TOKEN() + { + } + GIM_RSORT_TOKEN(const GIM_RSORT_TOKEN& rtoken) + { + m_key = rtoken.m_key; + m_value = rtoken.m_value; + } + + inline bool operator <(const GIM_RSORT_TOKEN& other) const + { + return (m_key < other.m_key); + } + + inline bool operator >(const GIM_RSORT_TOKEN& other) const + { + return (m_key > other.m_key); + } +}; + +//! Prototype for comparators +class GIM_RSORT_TOKEN_COMPARATOR +{ + public: + + inline int operator()( const GIM_RSORT_TOKEN& a, const GIM_RSORT_TOKEN& b ) + { + return (int)((a.m_key) - (b.m_key)); + } +}; + + + +#define kHist 2048 +// ---- utils for accessing 11-bit quantities +#define D11_0(x) (x & 0x7FF) +#define D11_1(x) (x >> 11 & 0x7FF) +#define D11_2(x) (x >> 22 ) + + + +///Radix sort for unsigned integer keys +inline void gim_radix_sort_rtokens( + GIM_RSORT_TOKEN * array, + GIM_RSORT_TOKEN * sorted, GUINT element_count) +{ + GUINT i; + GUINT b0[kHist * 3]; + GUINT *b1 = b0 + kHist; + GUINT *b2 = b1 + kHist; + for (i = 0; i < kHist * 3; ++i) + { + b0[i] = 0; + } + GUINT fi; + GUINT pos; + for (i = 0; i < element_count; ++i) + { + fi = array[i].m_key; + b0[D11_0(fi)] ++; + b1[D11_1(fi)] ++; + b2[D11_2(fi)] ++; + } + { + GUINT sum0 = 0, sum1 = 0, sum2 = 0; + GUINT tsum; + for (i = 0; i < kHist; ++i) + { + tsum = b0[i] + sum0; + b0[i] = sum0 - 1; + sum0 = tsum; + tsum = b1[i] + sum1; + b1[i] = sum1 - 1; + sum1 = tsum; + tsum = b2[i] + sum2; + b2[i] = sum2 - 1; + sum2 = tsum; + } + } + for (i = 0; i < element_count; ++i) + { + fi = array[i].m_key; + pos = D11_0(fi); + pos = ++b0[pos]; + sorted[pos].m_key = array[i].m_key; + sorted[pos].m_value = array[i].m_value; + } + for (i = 0; i < element_count; ++i) + { + fi = sorted[i].m_key; + pos = D11_1(fi); + pos = ++b1[pos]; + array[pos].m_key = sorted[i].m_key; + array[pos].m_value = sorted[i].m_value; + } + for (i = 0; i < element_count; ++i) + { + fi = array[i].m_key; + pos = D11_2(fi); + pos = ++b2[pos]; + sorted[pos].m_key = array[i].m_key; + sorted[pos].m_value = array[i].m_value; + } +} + + + + +/// Get the sorted tokens from an array. For generic use. Tokens are IRR_RSORT_TOKEN +/*! +*\param array Array of elements to sort +*\param sorted_tokens Tokens of sorted elements +*\param element_count element count +*\param uintkey_macro Functor which retrieves the integer representation of an array element +*/ +template +void gim_radix_sort_array_tokens( + T* array , + GIM_RSORT_TOKEN * sorted_tokens, + GUINT element_count,GETKEY_CLASS uintkey_macro) +{ + GIM_RSORT_TOKEN * _unsorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count); + for (GUINT _i=0;_i +void gim_radix_sort( + T * array, GUINT element_count, + GETKEY_CLASS get_uintkey_macro, COPY_CLASS copy_elements_macro) +{ + GIM_RSORT_TOKEN * _sorted = (GIM_RSORT_TOKEN *) gim_alloc(sizeof(GIM_RSORT_TOKEN)*element_count); + gim_radix_sort_array_tokens(array,_sorted,element_count,get_uintkey_macro); + T * _original_array = (T *) gim_alloc(sizeof(T)*element_count); + gim_simd_memcpy(_original_array,array,sizeof(T)*element_count); + for (GUINT _i=0;_i +bool gim_binary_search_ex( + const T* _array, GUINT _start_i, + GUINT _end_i,GUINT & _result_index, + const KEYCLASS & _search_key, + COMP_CLASS _comp_macro) +{ + GUINT _k; + int _comp_result; + GUINT _i = _start_i; + GUINT _j = _end_i+1; + while (_i < _j) + { + _k = (_j+_i-1)/2; + _comp_result = _comp_macro(_array[_k], _search_key); + if (_comp_result == 0) + { + _result_index = _k; + return true; + } + else if (_comp_result < 0) + { + _i = _k+1; + } + else + { + _j = _k; + } + } + _result_index = _i; + return false; +} + + + +//! Failsafe Iterative binary search,Template version +/*! +If the element is not found, it returns the nearest upper element position, may be the further position after the last element. +\param _array +\param _start_i the beginning of the array +\param _end_i the ending index of the array +\param _search_key Value to find +\param _result_index the index of the found element, or if not found then it will get the index of the closest bigger value +\return true if found, else false +*/ +template +bool gim_binary_search( + const T*_array,GUINT _start_i, + GUINT _end_i,const T & _search_key, + GUINT & _result_index) +{ + GUINT _i = _start_i; + GUINT _j = _end_i+1; + GUINT _k; + while(_i < _j) + { + _k = (_j+_i-1)/2; + if(_array[_k]==_search_key) + { + _result_index = _k; + return true; + } + else if (_array[_k]<_search_key) + { + _i = _k+1; + } + else + { + _j = _k; + } + } + _result_index = _i; + return false; +} + + + +///heap sort from http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/ +template +void gim_down_heap(T *pArr, GUINT k, GUINT n,COMP_CLASS CompareFunc) +{ + /* PRE: a[k+1..N] is a heap */ + /* POST: a[k..N] is a heap */ + + T temp = pArr[k - 1]; + /* k has child(s) */ + while (k <= n/2) + { + int child = 2*k; + + if ((child < (int)n) && CompareFunc(pArr[child - 1] , pArr[child])<0) + { + child++; + } + /* pick larger child */ + if (CompareFunc(temp , pArr[child - 1])<0) + { + /* move child up */ + pArr[k - 1] = pArr[child - 1]; + k = child; + } + else + { + break; + } + } + pArr[k - 1] = temp; +} /*downHeap*/ + + +template +void gim_heap_sort(T *pArr, GUINT element_count, COMP_CLASS CompareFunc) +{ + /* sort a[0..N-1], N.B. 0 to N-1 */ + GUINT k; + GUINT n = element_count; + for (k = n/2; k > 0; k--) + { + gim_down_heap(pArr, k, n, CompareFunc); + } + + /* a[1..N] is now a heap */ + while ( n>=2 ) + { + gim_swap_elements(pArr,0,n-1); /* largest of a[0..n-1] */ + --n; + /* restore a[1..i-1] heap */ + gim_down_heap(pArr, 1, n, CompareFunc); + } +} + + + +//! @} +#endif // GIM_RADIXSORT_H_INCLUDED diff --git a/extern/bullet2/src/BulletCollision/Gimpact/gim_tri_collision.cpp b/extern/bullet2/src/BulletCollision/Gimpact/gim_tri_collision.cpp new file mode 100644 index 00000000000..73c11c0fe0b --- /dev/null +++ b/extern/bullet2/src/BulletCollision/Gimpact/gim_tri_collision.cpp @@ -0,0 +1,640 @@ + +/*! \file gim_tri_collision.h +\author Francisco León Nájera +*/ +/* +----------------------------------------------------------------------------- +This source file is part of GIMPACT Library. + +For the latest info, see http://gimpact.sourceforge.net/ + +Copyright (c) 2006 Francisco Leon Najera. C.C. 80087371. +email: projectileman@yahoo.com + + This library is free software; you can redistribute it and/or + modify it under the terms of EITHER: + (1) The GNU Lesser General Public License as published by the Free + Software Foundation; either version 2.1 of the License, or (at + your option) any later version. The text of the GNU Lesser + General Public License is included with this library in the + file GIMPACT-LICENSE-LGPL.TXT. + (2) The BSD-style license that is included with this library in + the file GIMPACT-LICENSE-BSD.TXT. + (3) The zlib/libpng license that is included with this library in + the file GIMPACT-LICENSE-ZLIB.TXT. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files + GIMPACT-LICENSE-LGPL.TXT, GIMPACT-LICENSE-ZLIB.TXT and GIMPACT-LICENSE-BSD.TXT for more details. + +----------------------------------------------------------------------------- +*/ + +#include "gim_tri_collision.h" + + +#define TRI_LOCAL_EPSILON 0.000001f +#define MIN_EDGE_EDGE_DIS 0.00001f + + +class _GIM_TRIANGLE_CALCULATION_CACHE +{ +public: + GREAL margin; + btVector3 tu_vertices[3]; + btVector3 tv_vertices[3]; + btVector4 tu_plane; + btVector4 tv_plane; + btVector3 closest_point_u; + btVector3 closest_point_v; + btVector3 edge_edge_dir; + btVector3 distances; + GREAL du[4]; + GREAL du0du1; + GREAL du0du2; + GREAL dv[4]; + GREAL dv0dv1; + GREAL dv0dv2; + btVector3 temp_points[MAX_TRI_CLIPPING]; + btVector3 temp_points1[MAX_TRI_CLIPPING]; + btVector3 contact_points[MAX_TRI_CLIPPING]; + + + + //! if returns false, the faces are paralele + SIMD_FORCE_INLINE bool compute_intervals( + const GREAL &D0, + const GREAL &D1, + const GREAL &D2, + const GREAL &D0D1, + const GREAL &D0D2, + GREAL & scale_edge0, + GREAL & scale_edge1, + GUINT &edge_index0, + GUINT &edge_index1) + { + if(D0D1>0.0f) + { + /* here we know that D0D2<=0.0 */ + /* that is D0, D1 are on the same side, D2 on the other or on the plane */ + scale_edge0 = -D2/(D0-D2); + scale_edge1 = -D1/(D2-D1); + edge_index0 = 2;edge_index1 = 1; + } + else if(D0D2>0.0f) + { + /* here we know that d0d1<=0.0 */ + scale_edge0 = -D0/(D1-D0); + scale_edge1 = -D1/(D2-D1); + edge_index0 = 0;edge_index1 = 1; + } + else if(D1*D2>0.0f || D0!=0.0f) + { + /* here we know that d0d1<=0.0 or that D0!=0.0 */ + scale_edge0 = -D0/(D1-D0); + scale_edge1 = -D2/(D0-D2); + edge_index0 = 0 ;edge_index1 = 2; + } + else + { + return false; + } + return true; + } + + + //! clip triangle + /*! + */ + SIMD_FORCE_INLINE GUINT clip_triangle( + const btVector4 & tri_plane, + const btVector3 * tripoints, + const btVector3 * srcpoints, + btVector3 * clip_points) + { + // edge 0 + + btVector4 edgeplane; + + EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane); + + GUINT clipped_count = PLANE_CLIP_TRIANGLE3D( + edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points); + + if(clipped_count == 0) return 0; + + // edge 1 + + EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane); + + clipped_count = PLANE_CLIP_POLYGON3D( + edgeplane,temp_points,clipped_count,temp_points1); + + if(clipped_count == 0) return 0; + + // edge 2 + + EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane); + + clipped_count = PLANE_CLIP_POLYGON3D( + edgeplane,temp_points1,clipped_count,clip_points); + + return clipped_count; + + + /*GUINT i0 = (tri_plane.closestAxis()+1)%3; + GUINT i1 = (i0+1)%3; + // edge 0 + btVector3 temp_points[MAX_TRI_CLIPPING]; + btVector3 temp_points1[MAX_TRI_CLIPPING]; + + GUINT clipped_count= PLANE_CLIP_TRIANGLE_GENERIC( + 0,srcpoints[0],srcpoints[1],srcpoints[2],temp_points, + DISTANCE_EDGE(tripoints[0],tripoints[1],i0,i1)); + + + if(clipped_count == 0) return 0; + + // edge 1 + clipped_count = PLANE_CLIP_POLYGON_GENERIC( + 0,temp_points,clipped_count,temp_points1, + DISTANCE_EDGE(tripoints[1],tripoints[2],i0,i1)); + + if(clipped_count == 0) return 0; + + // edge 2 + clipped_count = PLANE_CLIP_POLYGON_GENERIC( + 0,temp_points1,clipped_count,clipped_points, + DISTANCE_EDGE(tripoints[2],tripoints[0],i0,i1)); + + return clipped_count;*/ + } + + SIMD_FORCE_INLINE void sort_isect( + GREAL & isect0,GREAL & isect1,GUINT &e0,GUINT &e1,btVector3 & vec0,btVector3 & vec1) + { + if(isect1=isect_v[1]) // face U casts face V + { + return 1; + } + else if(isect_v[0]<=isect_u[0]) // face V casts face U + { + return 2; + } + // closest points + closest_point_u = up_e1; + closest_point_v = vp_e0; + // calc edges and separation + + if(isect_u[1]+ MIN_EDGE_EDGE_DIS=isect_u[1]) // face V casts face U + { + return 2; + } + else if(isect_u[0]<=isect_v[0]) // face U casts face V + { + return 1; + } + // closest points + closest_point_u = up_e0; + closest_point_v = vp_e1; + // calc edges and separation + + if(isect_v[1]+MIN_EDGE_EDGE_DIS0.0f && du0du2>0.0f) // same sign on all of them + not equal 0 ? + { + if(du[0]<0) //we need test behind the triangle plane + { + distances[0] = GIM_MAX3(du[0],du[1],du[2]); + distances[0] = -distances[0]; + if(distances[0]>margin) return false; //never intersect + + //reorder triangle v + VEC_SWAP(tv_vertices[0],tv_vertices[1]); + VEC_SCALE_4(tv_plane,-1.0f,tv_plane); + } + else + { + distances[0] = GIM_MIN3(du[0],du[1],du[2]); + if(distances[0]>margin) return false; //never intersect + } + } + else + { + //Look if we need to invert the triangle + distances[0] = (du[0]+du[1]+du[2])/3.0f; //centroid + + if(distances[0]<0.0f) + { + //reorder triangle v + VEC_SWAP(tv_vertices[0],tv_vertices[1]); + VEC_SCALE_4(tv_plane,-1.0f,tv_plane); + + distances[0] = GIM_MAX3(du[0],du[1],du[2]); + distances[0] = -distances[0]; + } + else + { + distances[0] = GIM_MIN3(du[0],du[1],du[2]); + } + } + + + // plane U vs V points + + TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],tu_plane); + + dv[0] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[0]); + dv[1] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[1]); + dv[2] = DISTANCE_PLANE_POINT(tu_plane,tv_vertices[2]); + + dv0dv1 = dv[0] * dv[1]; + dv0dv2 = dv[0] * dv[2]; + + + if(dv0dv1>0.0f && dv0dv2>0.0f) // same sign on all of them + not equal 0 ? + { + if(dv[0]<0) //we need test behind the triangle plane + { + distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]); + distances[1] = -distances[1]; + if(distances[1]>margin) return false; //never intersect + + //reorder triangle u + VEC_SWAP(tu_vertices[0],tu_vertices[1]); + VEC_SCALE_4(tu_plane,-1.0f,tu_plane); + } + else + { + distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]); + if(distances[1]>margin) return false; //never intersect + } + } + else + { + //Look if we need to invert the triangle + distances[1] = (dv[0]+dv[1]+dv[2])/3.0f; //centroid + + if(distances[1]<0.0f) + { + //reorder triangle v + VEC_SWAP(tu_vertices[0],tu_vertices[1]); + VEC_SCALE_4(tu_plane,-1.0f,tu_plane); + + distances[1] = GIM_MAX3(dv[0],dv[1],dv[2]); + distances[1] = -distances[1]; + } + else + { + distances[1] = GIM_MIN3(dv[0],dv[1],dv[2]); + } + } + + GUINT bl; + /* bl = cross_line_intersection_test(); + if(bl==3) + { + //take edge direction too + bl = distances.maxAxis(); + } + else + {*/ + bl = 0; + if(distances[0]margin) return false; + + contacts.m_penetration_depth = -distances[2] + margin; + contacts.m_points[0] = closest_point_v; + contacts.m_point_count = 1; + VEC_COPY(contacts.m_separating_normal,edge_edge_dir); + + return true; + } + + //clip face against other + + + GUINT point_count; + //TODO + if(bl == 0) //clip U points against V + { + point_count = clip_triangle(tv_plane,tv_vertices,tu_vertices,contact_points); + if(point_count == 0) return false; + contacts.merge_points(tv_plane,margin,contact_points,point_count); + } + else //clip V points against U + { + point_count = clip_triangle(tu_plane,tu_vertices,tv_vertices,contact_points); + if(point_count == 0) return false; + contacts.merge_points(tu_plane,margin,contact_points,point_count); + contacts.m_separating_normal *= -1.f; + } + if(contacts.m_point_count == 0) return false; + return true; + } + +}; + + +/*class _GIM_TRIANGLE_CALCULATION_CACHE +{ +public: + GREAL margin; + GUINT clipped_count; + btVector3 tu_vertices[3]; + btVector3 tv_vertices[3]; + btVector3 temp_points[MAX_TRI_CLIPPING]; + btVector3 temp_points1[MAX_TRI_CLIPPING]; + btVector3 clipped_points[MAX_TRI_CLIPPING]; + GIM_TRIANGLE_CONTACT_DATA contacts1; + GIM_TRIANGLE_CONTACT_DATA contacts2; + + + //! clip triangle + GUINT clip_triangle( + const btVector4 & tri_plane, + const btVector3 * tripoints, + const btVector3 * srcpoints, + btVector3 * clipped_points) + { + // edge 0 + + btVector4 edgeplane; + + EDGE_PLANE(tripoints[0],tripoints[1],tri_plane,edgeplane); + + GUINT clipped_count = PLANE_CLIP_TRIANGLE3D( + edgeplane,srcpoints[0],srcpoints[1],srcpoints[2],temp_points); + + if(clipped_count == 0) return 0; + + // edge 1 + + EDGE_PLANE(tripoints[1],tripoints[2],tri_plane,edgeplane); + + clipped_count = PLANE_CLIP_POLYGON3D( + edgeplane,temp_points,clipped_count,temp_points1); + + if(clipped_count == 0) return 0; + + // edge 2 + + EDGE_PLANE(tripoints[2],tripoints[0],tri_plane,edgeplane); + + clipped_count = PLANE_CLIP_POLYGON3D( + edgeplane,temp_points1,clipped_count,clipped_points); + + return clipped_count; + } + + + + + //! collides only on one side + bool triangle_collision( + const btVector3 & u0, + const btVector3 & u1, + const btVector3 & u2, + GREAL margin_u, + const btVector3 & v0, + const btVector3 & v1, + const btVector3 & v2, + GREAL margin_v, + GIM_TRIANGLE_CONTACT_DATA & contacts) + { + + margin = margin_u + margin_v; + + + tu_vertices[0] = u0; + tu_vertices[1] = u1; + tu_vertices[2] = u2; + + tv_vertices[0] = v0; + tv_vertices[1] = v1; + tv_vertices[2] = v2; + + //create planes + // plane v vs U points + + + TRIANGLE_PLANE(tv_vertices[0],tv_vertices[1],tv_vertices[2],contacts1.m_separating_normal); + + clipped_count = clip_triangle( + contacts1.m_separating_normal,tv_vertices,tu_vertices,clipped_points); + + if(clipped_count == 0 ) + { + return false;//Reject + } + + //find most deep interval face1 + contacts1.merge_points(contacts1.m_separating_normal,margin,clipped_points,clipped_count); + if(contacts1.m_point_count == 0) return false; // too far + + //Normal pointing to triangle1 + //contacts1.m_separating_normal *= -1.f; + + //Clip tri1 by tri2 edges + + TRIANGLE_PLANE(tu_vertices[0],tu_vertices[1],tu_vertices[2],contacts2.m_separating_normal); + + clipped_count = clip_triangle( + contacts2.m_separating_normal,tu_vertices,tv_vertices,clipped_points); + + if(clipped_count == 0 ) + { + return false;//Reject + } + + //find most deep interval face1 + contacts2.merge_points(contacts2.m_separating_normal,margin,clipped_points,clipped_count); + if(contacts2.m_point_count == 0) return false; // too far + + contacts2.m_separating_normal *= -1.f; + + ////check most dir for contacts + if(contacts2.m_penetration_depth + SIMD_FORCE_INLINE void mergepoints_generic(const CLASS_PLANE & plane, + GREAL margin, const btVector3 * points, GUINT point_count, DISTANCE_FUNC distance_func) + { + m_point_count = 0; + m_penetration_depth= -1000.0f; + + GUINT point_indices[MAX_TRI_CLIPPING]; + + GUINT _k; + + for(_k=0;_k=0.0f) + { + if(_dist>m_penetration_depth) + { + m_penetration_depth = _dist; + point_indices[0] = _k; + m_point_count=1; + } + else if((_dist+G_EPSILON)>=m_penetration_depth) + { + point_indices[m_point_count] = _k; + m_point_count++; + } + } + } + + for( _k=0;_k u*axe1[i1] + ((vecproj[i2] - u*axe1[i2])/axe2[i2])*axe2[i1] = vecproj[i1] + + --> u*axe1[i1] + vecproj[i2]*axe2[i1]/axe2[i2] - u*axe1[i2]*axe2[i1]/axe2[i2] = vecproj[i1] + + --> u*(axe1[i1] - axe1[i2]*axe2[i1]/axe2[i2]) = vecproj[i1] - vecproj[i2]*axe2[i1]/axe2[i2] + + --> u*((axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1])/axe2[i2]) = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1])/axe2[i2] + + --> u*(axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1]) = vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1] + + --> u = (vecproj[i1]*axe2[i2] - vecproj[i2]*axe2[i1]) /(axe1[i1]*axe2[i2] - axe1[i2]*axe2[i1]) + +if 0.0<= u+v <=1.0 then they are inside of triangle + + \return false if the point is outside of triangle.This function doesn't take the margin + */ + SIMD_FORCE_INLINE bool get_uv_parameters( + const btVector3 & point, + const btVector3 & tri_plane, + GREAL & u, GREAL & v) const + { + btVector3 _axe1 = m_vertices[1]-m_vertices[0]; + btVector3 _axe2 = m_vertices[2]-m_vertices[0]; + btVector3 _vecproj = point - m_vertices[0]; + GUINT _i1 = (tri_plane.closestAxis()+1)%3; + GUINT _i2 = (_i1+1)%3; + if(btFabs(_axe2[_i2])G_EPSILON) + { + return false; + } + } + return true; + } + + //! is point in triangle beam? + /*! + Test if point is in triangle, with m_margin tolerance + */ + SIMD_FORCE_INLINE bool is_point_inside(const btVector3 & point, const btVector3 & tri_normal) const + { + //Test with edge 0 + btVector4 edge_plane; + this->get_edge_plane(0,tri_normal,edge_plane); + GREAL dist = DISTANCE_PLANE_POINT(edge_plane,point); + if(dist-m_margin>0.0f) return false; // outside plane + + this->get_edge_plane(1,tri_normal,edge_plane); + dist = DISTANCE_PLANE_POINT(edge_plane,point); + if(dist-m_margin>0.0f) return false; // outside plane + + this->get_edge_plane(2,tri_normal,edge_plane); + dist = DISTANCE_PLANE_POINT(edge_plane,point); + if(dist-m_margin>0.0f) return false; // outside plane + return true; + } + + + //! Bidireccional ray collision + SIMD_FORCE_INLINE bool ray_collision( + const btVector3 & vPoint, + const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal, + GREAL & tparam, GREAL tmax = G_REAL_INFINITY) + { + btVector4 faceplane; + { + btVector3 dif1 = m_vertices[1] - m_vertices[0]; + btVector3 dif2 = m_vertices[2] - m_vertices[0]; + VEC_CROSS(faceplane,dif1,dif2); + faceplane[3] = m_vertices[0].dot(faceplane); + } + + GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax); + if(res == 0) return false; + if(! is_point_inside(pout,faceplane)) return false; + + if(res==2) //invert normal + { + triangle_normal.setValue(-faceplane[0],-faceplane[1],-faceplane[2]); + } + else + { + triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]); + } + + VEC_NORMALIZE(triangle_normal); + + return true; + } + + + //! one direccion ray collision + SIMD_FORCE_INLINE bool ray_collision_front_side( + const btVector3 & vPoint, + const btVector3 & vDir, btVector3 & pout, btVector3 & triangle_normal, + GREAL & tparam, GREAL tmax = G_REAL_INFINITY) + { + btVector4 faceplane; + { + btVector3 dif1 = m_vertices[1] - m_vertices[0]; + btVector3 dif2 = m_vertices[2] - m_vertices[0]; + VEC_CROSS(faceplane,dif1,dif2); + faceplane[3] = m_vertices[0].dot(faceplane); + } + + GUINT res = LINE_PLANE_COLLISION(faceplane,vDir,vPoint,pout,tparam, btScalar(0), tmax); + if(res != 1) return false; + + if(!is_point_inside(pout,faceplane)) return false; + + triangle_normal.setValue(faceplane[0],faceplane[1],faceplane[2]); + + VEC_NORMALIZE(triangle_normal); + + return true; + } + +}; + + + +//! @} + +#endif // GIM_TRI_COLLISION_H_INCLUDED diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp index e42a613343b..7b7b2da910a 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp @@ -384,6 +384,20 @@ void btSoftBody::addVelocity(const btVector3& velocity) for(int i=0,ni=m_nodes.size();i0) + { + n.m_v = velocity; + } + } +} + + // void btSoftBody::addVelocity(const btVector3& velocity,int node) { diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.h b/extern/bullet2/src/BulletSoftBody/btSoftBody.h index e89bbcc4fa8..7a6bfd53205 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBody.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.h @@ -677,6 +677,10 @@ public: int node); /* Add velocity to the entire body */ void addVelocity( const btVector3& velocity); + + /* Set velocity for the entire body */ + void setVelocity( const btVector3& velocity); + /* Add velocity to a node of the body */ void addVelocity( const btVector3& velocity, int node); diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript index 77d94bc8dab..babd4e671f6 100644 --- a/extern/bullet2/src/SConscript +++ b/extern/bullet2/src/SConscript @@ -25,7 +25,7 @@ linearmath_src = env.Glob("LinearMath/*.cpp") bulletdyn_src = env.Glob("BulletDynamics/Vehicle/*.cpp") + env.Glob("BulletDynamics/ConstraintSolver/*.cpp") + env.Glob("BulletDynamics/Dynamics/*.cpp") -collision_src = env.Glob("BulletCollision/BroadphaseCollision/*.cpp") + env.Glob("BulletCollision/CollisionDispatch/*.cpp") +collision_src = env.Glob("BulletCollision/BroadphaseCollision/*.cpp") + env.Glob("BulletCollision/CollisionDispatch/*.cpp") + env.Glob("BulletCollision/Gimpact/*.cpp") collision_src += env.Glob("BulletCollision/CollisionShapes/*.cpp") + env.Glob("BulletCollision/NarrowPhaseCollision/*.cpp") softbody_src = env.Glob("BulletSoftBody/*.cpp") diff --git a/source/gameengine/Converter/BL_DeformableGameObject.cpp b/source/gameengine/Converter/BL_DeformableGameObject.cpp index 1d62a41cce9..e2610d2b405 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.cpp +++ b/source/gameengine/Converter/BL_DeformableGameObject.cpp @@ -47,7 +47,7 @@ void BL_DeformableGameObject::ProcessReplica(KX_GameObject* replica) KX_GameObject::ProcessReplica(replica); if (m_pDeformer) { - deformer = (BL_MeshDeformer*)m_pDeformer->GetReplica(); + deformer = (BL_MeshDeformer*)m_pDeformer->GetReplica(replica); ((BL_DeformableGameObject*)replica)->m_pDeformer = deformer; } diff --git a/source/gameengine/Converter/BL_MeshDeformer.h b/source/gameengine/Converter/BL_MeshDeformer.h index 9d3d2e78123..8de59c1cdf3 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.h +++ b/source/gameengine/Converter/BL_MeshDeformer.h @@ -64,7 +64,7 @@ public: virtual void SetSimulatedTime(double time){}; virtual bool Apply(class RAS_IPolyMaterial *mat); virtual bool Update(void){ return false; }; - virtual RAS_Deformer* GetReplica(){return NULL;}; + virtual RAS_Deformer* GetReplica(class KX_GameObject* replica){return NULL;}; struct Mesh* GetMesh() { return m_bmesh; }; // virtual void InitDeform(double time){}; diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp index dfd33e45fef..fc6498579ad 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.cpp +++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp @@ -68,7 +68,7 @@ BL_ShapeDeformer::~BL_ShapeDeformer() { }; -RAS_Deformer *BL_ShapeDeformer::GetReplica() +RAS_Deformer *BL_ShapeDeformer::GetReplica(class KX_GameObject* replica) { BL_ShapeDeformer *result; diff --git a/source/gameengine/Converter/BL_ShapeDeformer.h b/source/gameengine/Converter/BL_ShapeDeformer.h index 1465bb01e22..90b9f5caea1 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.h +++ b/source/gameengine/Converter/BL_ShapeDeformer.h @@ -66,7 +66,7 @@ public: }; virtual void ProcessReplica(); - virtual RAS_Deformer *GetReplica(); + virtual RAS_Deformer *GetReplica(class KX_GameObject* replica); virtual ~BL_ShapeDeformer(); bool Update (void); diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index b7b39ad7fbf..d8563763954 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -146,7 +146,7 @@ bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) return true; } -RAS_Deformer *BL_SkinDeformer::GetReplica() +RAS_Deformer *BL_SkinDeformer::GetReplica(class KX_GameObject* replica) { BL_SkinDeformer *result; diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h index e08de8c478a..f87860021c6 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.h +++ b/source/gameengine/Converter/BL_SkinDeformer.h @@ -67,7 +67,7 @@ public: BL_ArmatureObject* arma = NULL); virtual void ProcessReplica(); - virtual RAS_Deformer *GetReplica(); + virtual RAS_Deformer *GetReplica(class KX_GameObject* replica); virtual ~BL_SkinDeformer(); bool Update (void); bool Apply (class RAS_IPolyMaterial *polymat); diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 7e684e5d5b7..ddf1f402431 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -670,15 +670,12 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, class KX_SoftBodyDeformer : public RAS_Deformer { - btSoftBody* m_softBody; class RAS_MeshObject* m_pMeshObject; class KX_GameObject* m_gameobj; - public: - KX_SoftBodyDeformer(btSoftBody* softBody,RAS_MeshObject* pMeshObject,KX_GameObject* gameobj) - : m_softBody(softBody), - m_pMeshObject(pMeshObject), + KX_SoftBodyDeformer(RAS_MeshObject* pMeshObject,KX_GameObject* gameobj) + :m_pMeshObject(pMeshObject), m_gameobj(gameobj) { //printf("KX_SoftBodyDeformer\n"); @@ -694,6 +691,14 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, } virtual bool Apply(class RAS_IPolyMaterial *polymat) { + KX_BulletPhysicsController* ctrl = (KX_BulletPhysicsController*) m_gameobj->GetPhysicsController(); + if (!ctrl) + return false; + + btSoftBody* softBody= ctrl->GetSoftBody(); + if (!softBody) + return false; + //printf("apply\n"); RAS_MeshSlot::iterator it; RAS_MeshMaterial *mmat; @@ -718,11 +723,12 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, // for each array for(slot->begin(it); !slot->end(it); slot->next(it)) { - btSoftBody::tNodeArray& nodes(m_softBody->m_nodes); + btSoftBody::tNodeArray& nodes(softBody->m_nodes); int index = 0; for(i=it.startvertex; i= 0); MT_Point3 pt ( nodes[v.getSoftBodyIndex()].m_x.getX(), @@ -745,10 +751,10 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, //printf("update\n"); return true;//?? } - virtual RAS_Deformer *GetReplica() + virtual RAS_Deformer *GetReplica(class KX_GameObject* replica) { - //printf("getReplica\n"); - return 0; + KX_SoftBodyDeformer* deformer = new KX_SoftBodyDeformer(replica->GetMesh(0),replica); + return deformer; } virtual bool SkipVertexTransform() @@ -855,12 +861,13 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, } case KX_BOUNDPOLYTOPE: { - shapeInfo->SetMesh(meshobj, true); + shapeInfo->SetMesh(meshobj, true,false); bm = shapeInfo->CreateBulletShape(); break; } case KX_BOUNDMESH: { + if (!ci.m_mass ||objprop->m_softbody) { // mesh shapes can be shared, check first if we already have a shape on that mesh @@ -872,11 +879,15 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, shapeInfo->AddRef(); } else { - shapeInfo->SetMesh(meshobj, false); + shapeInfo->SetMesh(meshobj, false,false); } bm = shapeInfo->CreateBulletShape(); //no moving concave meshes, so don't bother calculating inertia //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor); + } else + { + shapeInfo->SetMesh(meshobj, false,true); + bm = shapeInfo->CreateBulletShape(); } break; @@ -1097,7 +1108,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, if (softBody && gameobj->GetMesh(0))//only the first mesh, if any { //should be a mesh then, so add a soft body deformer - KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer(softBody, gameobj->GetMesh(0),gameobj); + KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer( gameobj->GetMesh(0),gameobj); gameobj->SetDeformer(softbodyDeformer); } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 29ee0310c58..d552cb3dc9e 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -23,6 +23,8 @@ subject to the following restrictions: #include "BulletSoftBody//btSoftBodyInternals.h" #include "BulletSoftBody/btSoftBodyHelpers.h" #include "LinearMath/btConvexHull.h" +#include "BulletCollision/Gimpact/btGImpactShape.h" + #include "BulletSoftBody/btSoftRigidDynamicsWorld.h" @@ -46,10 +48,13 @@ btVector3 startVel(0,0,0);//-10000); CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci) :m_cci(ci) { + m_prototypeTransformInitialized = false; + m_softbodyMappingDone = false; m_collisionDelay = 0; m_newClientInfo = 0; m_registerCount = 0; - + m_softBodyTransformInitialized = false; + // copy pointers locally to allow smart release m_MotionState = ci.m_MotionState; m_collisionShape = ci.m_collisionShape; @@ -144,7 +149,7 @@ btSoftBody* CcdPhysicsController::GetSoftBody() void CcdPhysicsController::CreateRigidbody() { - btTransform trans = GetTransformFromMotionState(m_MotionState); + //btTransform trans = GetTransformFromMotionState(m_MotionState); m_bulletMotionState = new BlenderBulletMotionState(m_MotionState); ///either create a btCollisionObject, btRigidBody or btSoftBody @@ -189,18 +194,12 @@ void CcdPhysicsController::CreateRigidbody() if (m_cci.m_collisionShape->getShapeType() == CONVEX_HULL_SHAPE_PROXYTYPE) { btConvexHullShape* convexHull = (btConvexHullShape* )m_cci.m_collisionShape; - btAlignedObjectArray transformedVertices; - transformedVertices.resize(convexHull->getNumPoints()); - for (int i=0;igetNumPoints();i++) - { - transformedVertices[i] = trans(convexHull->getPoints()[i]); - } //psb = btSoftBodyHelpers::CreateFromConvexHull(sbi,&transformedVertices[0],convexHull->getNumPoints()); { int nvertices = convexHull->getNumPoints(); - const btVector3* vertices = &transformedVertices[0]; + const btVector3* vertices = convexHull->getPoints(); btSoftBodyWorldInfo& worldInfo = softDynaWorld->getWorldInfo(); HullDesc hdsc(QF_TRIANGLES,nvertices,vertices); @@ -226,7 +225,7 @@ void CcdPhysicsController::CreateRigidbody() { RAS_MeshObject* rasMesh= GetShapeInfo()->GetMesh(); - if (rasMesh) + if (rasMesh && !m_softbodyMappingDone) { //printf("apply\n"); @@ -251,17 +250,20 @@ void CcdPhysicsController::CreateRigidbody() for(i=it.startvertex; isetSoftBodyIndex(0); btScalar maxDistSqr = 1e30; btSoftBody::tNodeArray& nodes(psb->m_nodes); - btVector3 xyz = trans(btVector3(vertex->getXYZ()[0],vertex->getXYZ()[1],vertex->getXYZ()[2])); + btVector3 xyz = btVector3(vertex->getXYZ()[0],vertex->getXYZ()[1],vertex->getXYZ()[2]); for (int n=0;nsetSoftBodyIndex(n); } } @@ -330,6 +332,7 @@ void CcdPhysicsController::CreateRigidbody() } + m_softbodyMappingDone = true; m_object = psb; @@ -408,6 +411,13 @@ void CcdPhysicsController::CreateRigidbody() m_MotionState->setWorldPosition(startTrans.getOrigin().getX(),startTrans.getOrigin().getY(),startTrans.getOrigin().getZ()); m_MotionState->setWorldOrientation(0,0,0,1); + if (!m_prototypeTransformInitialized) + { + m_prototypeTransformInitialized = true; + m_softBodyTransformInitialized = true; + GetSoftBody()->transform(startTrans); + } + // btVector3 wp = m_softBody->getWorldTransform().getOrigin(); // MT_Point3 center(wp.getX(),wp.getY(),wp.getZ()); // m_gameobj->NodeSetWorldPosition(center); @@ -572,6 +582,7 @@ void CcdPhysicsController::WriteDynamicsToMotionState() // controller replication void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl) { + m_softBodyTransformInitialized=false; m_MotionState = motionstate; m_registerCount = 0; m_collisionShape = NULL; @@ -652,7 +663,7 @@ void CcdPhysicsController::SetCenterOfMassTransform(btTransform& xform) //either collision object or soft body? if (GetSoftBody()) { - //not yet + } else { @@ -761,6 +772,9 @@ void CcdPhysicsController::setOrientation(float quatImag0,float quatImag1,float SetCenterOfMassTransform(xform); // not required //m_bulletMotionState->setWorldTransform(xform); + + + } } @@ -781,6 +795,15 @@ void CcdPhysicsController::setWorldOrientation(const btMatrix3x3& orn) SetCenterOfMassTransform(xform); // not required //m_bulletMotionState->setWorldTransform(xform); + //only once! + if (!m_softBodyTransformInitialized && GetSoftBody()) + { + m_softbodyStartTrans.setBasis(orn); + xform.setOrigin(m_softbodyStartTrans.getOrigin()); + GetSoftBody()->transform(xform); + m_softBodyTransformInitialized = true; + } + } } @@ -799,6 +822,8 @@ void CcdPhysicsController::setPosition(float posX,float posY,float posZ) btTransform xform = m_object->getWorldTransform(); xform.setOrigin(btVector3(posX,posY,posZ)); SetCenterOfMassTransform(xform); + if (!m_softBodyTransformInitialized) + m_softbodyStartTrans.setOrigin(xform.getOrigin()); // not required //m_bulletMotionState->setWorldTransform(xform); } @@ -931,6 +956,15 @@ void CcdPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,floa m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } + btSoftBody* soft = GetSoftBody(); + if (soft) + { + if (local) + { + linVel = m_softbodyStartTrans.getBasis()*linVel; + } + soft->setVelocity(linVel); + } else { btTransform xform = m_object->getWorldTransform(); if (local) @@ -940,7 +974,6 @@ void CcdPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,floa btRigidBody* body = GetRigidBody(); if (body) body->setLinearVelocity(linVel); - } } } @@ -1186,8 +1219,10 @@ CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mes return NULL; } -bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope) +bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bool useGimpact) { + m_useGimpact = useGimpact; + // assume no shape information // no support for dynamic change of shape yet assert(m_meshObject == NULL); @@ -1353,19 +1388,35 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() // 9 multiplications/additions and one function call for each triangle that passes the mid phase filtering // One possible optimization is to use directly the btBvhTriangleMeshShape when the scale is 1,1,1 // and btScaledBvhTriangleMeshShape otherwise. - if (!m_unscaledShape) + if (m_useGimpact) { - collisionMeshData = new btTriangleMesh(); - // m_vertexArray is necessarily a multiple of 3 - for (std::vector::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) + collisionMeshData = new btTriangleMesh(); + // m_vertexArray is necessarily a multiple of 3 + for (std::vector::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) + { + collisionMeshData->addTriangle(*it++,*it++,*it++); + } + btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(collisionMeshData); + + collisionShape = gimpactShape; + gimpactShape->updateBound(); + + } else + { + if (!m_unscaledShape) { - collisionMeshData->addTriangle(*it++,*it++,*it++); + collisionMeshData = new btTriangleMesh(); + // m_vertexArray is necessarily a multiple of 3 + for (std::vector::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) + { + collisionMeshData->addTriangle(*it++,*it++,*it++); + } + // this shape will be shared and not deleted until shapeInfo is deleted + m_unscaledShape = new btBvhTriangleMeshShape( collisionMeshData, true ); + m_unscaledShape->recalcLocalAabb(); } - // this shape will be shared and not deleted until shapeInfo is deleted - m_unscaledShape = new btBvhTriangleMeshShape( collisionMeshData, true ); - m_unscaledShape->recalcLocalAabb(); + collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f)); } - collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f)); break; case PHY_SHAPE_COMPOUND: diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 65c23eb2543..5d35482dd46 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -53,7 +53,8 @@ public: m_childScale(1.0f,1.0f,1.0f), m_refCount(1), m_meshObject(NULL), - m_unscaledShape(NULL) + m_unscaledShape(NULL), + m_useGimpact(false) { m_childTrans.setIdentity(); } @@ -88,7 +89,7 @@ public: return m_shapeArray.at(i); } - bool SetMesh(RAS_MeshObject* mesh, bool polytope); + bool SetMesh(RAS_MeshObject* mesh, bool polytope,bool useGimpact); RAS_MeshObject* GetMesh(void) { return m_meshObject; @@ -118,6 +119,7 @@ protected: btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape, // the actual shape is of type btScaledBvhTriangleMeshShape std::vector m_shapeArray; // for compound shapes + bool m_useGimpact; }; struct CcdConstructionInfo @@ -211,6 +213,7 @@ class CcdPhysicsController : public PHY_IPhysicsController { btCollisionObject* m_object; + class PHY_IMotionState* m_MotionState; btMotionState* m_bulletMotionState; @@ -219,6 +222,12 @@ class CcdPhysicsController : public PHY_IPhysicsController friend class CcdPhysicsEnvironment; // needed when updating the controller + //some book keeping for replication + bool m_softbodyMappingDone; + bool m_softBodyTransformInitialized; + bool m_prototypeTransformInitialized; + btTransform m_softbodyStartTrans; + void* m_newClientInfo; int m_registerCount; // needed when multiple sensors use the same controller diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 8c5aae3f8c9..3593aecf3d5 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -25,6 +25,7 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" #include "BulletSoftBody/btSoftRigidDynamicsWorld.h" #include "BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h" +#include "BulletCollision/Gimpact/btGImpactCollisionAlgorithm.h" //profiling/timings #include "LinearMath/btQuickprof.h" @@ -338,7 +339,9 @@ m_filterCallback(NULL) if (!dispatcher) { - dispatcher = new btCollisionDispatcher(m_collisionConfiguration); + btCollisionDispatcher* disp = new btCollisionDispatcher(m_collisionConfiguration); + dispatcher = disp; + btGImpactCollisionAlgorithm::registerAlgorithm(disp); m_ownDispatcher = dispatcher; } diff --git a/source/gameengine/Rasterizer/RAS_Deformer.h b/source/gameengine/Rasterizer/RAS_Deformer.h index 6665e1926cf..3332ac4c0a7 100644 --- a/source/gameengine/Rasterizer/RAS_Deformer.h +++ b/source/gameengine/Rasterizer/RAS_Deformer.h @@ -44,7 +44,7 @@ public: virtual void Relink(GEN_Map*map)=0; virtual bool Apply(class RAS_IPolyMaterial *polymat)=0; virtual bool Update(void)=0; - virtual RAS_Deformer *GetReplica()=0; + virtual RAS_Deformer *GetReplica(class KX_GameObject* replica)=0; virtual bool SkipVertexTransform() { return false; diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp index d6f1fe912be..b92965ed1cc 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.cpp +++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp @@ -47,6 +47,7 @@ RAS_TexVert::RAS_TexVert(const MT_Point3& xyz, m_flag = (flat)? FLAT: 0; m_origindex = origindex; m_unit = 2; + m_softBodyIndex = -1; } const MT_Point3& RAS_TexVert::xyz() -- cgit v1.2.3 From 9d3c77ec6277b28993f76804cd975b3684a304e9 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Fri, 26 Sep 2008 06:25:35 +0000 Subject: support concave soft bodies, preliminary. could be used for cloth too. need vertex pinning/constraint attach to other objects. --- .../CollisionShapes/btTriangleMesh.cpp | 86 +++++++----- .../CollisionShapes/btTriangleMesh.h | 8 +- .../gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp | 3 + .../Physics/Bullet/CcdPhysicsController.cpp | 151 ++++++++++++--------- .../Physics/Bullet/CcdPhysicsController.h | 17 ++- 5 files changed, 162 insertions(+), 103 deletions(-) diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp index bcea97052d6..29d26316316 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.cpp @@ -19,7 +19,8 @@ subject to the following restrictions: btTriangleMesh::btTriangleMesh (bool use32bitIndices,bool use4componentVertices) :m_use32bitIndices(use32bitIndices), -m_use4componentVertices(use4componentVertices) +m_use4componentVertices(use4componentVertices), +m_weldingThreshold(0.0) { btIndexedMesh meshIndex; meshIndex.m_numTriangles = 0; @@ -60,49 +61,66 @@ m_use4componentVertices(use4componentVertices) } - -void btTriangleMesh::addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2) +void btTriangleMesh::addIndex(int index) { - m_indexedMeshes[0].m_numTriangles++; - m_indexedMeshes[0].m_numVertices+=3; - - if (m_use4componentVertices) + if (m_use32bitIndices) { - m_4componentVertices.push_back(vertex0); - m_4componentVertices.push_back(vertex1); - m_4componentVertices.push_back(vertex2); - m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0]; + m_32bitIndices.push_back(index); + m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0]; } else { - m_3componentVertices.push_back(vertex0.getX()); - m_3componentVertices.push_back(vertex0.getY()); - m_3componentVertices.push_back(vertex0.getZ()); - - m_3componentVertices.push_back(vertex1.getX()); - m_3componentVertices.push_back(vertex1.getY()); - m_3componentVertices.push_back(vertex1.getZ()); - - m_3componentVertices.push_back(vertex2.getX()); - m_3componentVertices.push_back(vertex2.getY()); - m_3componentVertices.push_back(vertex2.getZ()); - m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0]; + m_16bitIndices.push_back(index); + m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0]; } +} - if (m_use32bitIndices) +int btTriangleMesh::findOrAddVertex(const btVector3& vertex) +{ + //return index of new/existing vertex + //todo: could use acceleration structure for this + if (m_use4componentVertices) { - int curIndex = m_32bitIndices.size(); - m_32bitIndices.push_back(curIndex++); - m_32bitIndices.push_back(curIndex++); - m_32bitIndices.push_back(curIndex++); - m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_32bitIndices[0]; + for (int i=0;i< m_4componentVertices.size();i++) + { + if ((m_4componentVertices[i]-vertex).length2() <= m_weldingThreshold) + { + return i; + } + } + m_indexedMeshes[0].m_numVertices++; + m_4componentVertices.push_back(vertex); + m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_4componentVertices[0]; + + return m_4componentVertices.size()-1; + } else { - short curIndex = static_cast(m_16bitIndices.size()); - m_16bitIndices.push_back(curIndex++); - m_16bitIndices.push_back(curIndex++); - m_16bitIndices.push_back(curIndex++); - m_indexedMeshes[0].m_triangleIndexBase = (unsigned char*) &m_16bitIndices[0]; + + for (int i=0;i< m_3componentVertices.size();i+=3) + { + btVector3 vtx(m_3componentVertices[i],m_3componentVertices[i+1],m_3componentVertices[i+2]); + if ((vtx-vertex).length2() <= m_weldingThreshold) + { + return i/3; + } + } + m_3componentVertices.push_back(vertex.getX()); + m_3componentVertices.push_back(vertex.getY()); + m_3componentVertices.push_back(vertex.getZ()); + m_indexedMeshes[0].m_numVertices++; + m_indexedMeshes[0].m_vertexBase = (unsigned char*)&m_3componentVertices[0]; + return (m_3componentVertices.size()/3)-1; } + +} + +void btTriangleMesh::addTriangle(const btVector3& vertex0,const btVector3& vertex1,const btVector3& vertex2) +{ + m_indexedMeshes[0].m_numTriangles++; + + addIndex(findOrAddVertex(vertex0)); + addIndex(findOrAddVertex(vertex1)); + addIndex(findOrAddVertex(vertex2)); } int btTriangleMesh::getNumTriangles() const diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h index e4d41d5ede0..1f51b2f2c87 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMesh.h @@ -25,6 +25,7 @@ subject to the following restrictions: ///It allows either 32bit or 16bit indices, and 4 (x-y-z-w) or 3 (x-y-z) component vertices. ///If you want to share triangle/index data between graphics mesh and collision mesh (btBvhTriangleMeshShape), you can directly use btTriangleIndexVertexArray or derive your own class from btStridingMeshInterface. ///Performance of btTriangleMesh and btTriangleIndexVertexArray used in a btBvhTriangleMeshShape is the same. +///It has a brute-force option to weld together closeby vertices. class btTriangleMesh : public btTriangleIndexVertexArray { btAlignedObjectArray m_4componentVertices; @@ -34,11 +35,16 @@ class btTriangleMesh : public btTriangleIndexVertexArray btAlignedObjectArray m_16bitIndices; bool m_use32bitIndices; bool m_use4componentVertices; - + public: + btScalar m_weldingThreshold; + btTriangleMesh (bool use32bitIndices=true,bool use4componentVertices=true); + int findOrAddVertex(const btVector3& vertex); + void addIndex(int index); + bool getUse32bitIndices() const { return m_use32bitIndices; diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index ddf1f402431..c5dbabe24fc 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -881,6 +881,9 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, { shapeInfo->SetMesh(meshobj, false,false); } + if (objprop->m_softbody) + shapeInfo->setVertexWeldingThreshold(0.01f); //todo: expose this to the UI + bm = shapeInfo->CreateBulletShape(); //no moving concave meshes, so don't bother calculating inertia //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index d552cb3dc9e..f1e30b4a1e3 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -160,9 +160,9 @@ void CcdPhysicsController::CreateRigidbody() //disable soft body until first sneak preview is ready if (m_cci.m_bSoft && m_cci.m_collisionShape && - (shapeType == CONVEX_HULL_SHAPE_PROXYTYPE)) - //(shapeType == TRIANGLE_MESH_SHAPE_PROXYTYPE) | - //(shapeType == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE))) + (shapeType == CONVEX_HULL_SHAPE_PROXYTYPE)| + (shapeType == TRIANGLE_MESH_SHAPE_PROXYTYPE) | + (shapeType == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE)) { btRigidBody::btRigidBodyConstructionInfo rbci(m_cci.m_mass,m_bulletMotionState,m_collisionShape,m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); rbci.m_linearDamping = m_cci.m_linearDamping; @@ -221,57 +221,7 @@ void CcdPhysicsController::CreateRigidbody() psb->appendFace(idx[0],idx[1],idx[2]); } - ///create a mapping between graphics mesh vertices and soft body vertices - { - RAS_MeshObject* rasMesh= GetShapeInfo()->GetMesh(); - - if (rasMesh && !m_softbodyMappingDone) - { - - //printf("apply\n"); - RAS_MeshSlot::iterator it; - RAS_MeshMaterial *mmat; - RAS_MeshSlot *slot; - size_t i; - - //for each material - for (int m=0;mNumMaterials();m++) - { - // The vertex cache can only be updated for this deformer: - // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object) - // share the same mesh (=the same cache). As the rendering is done per polymaterial - // cycling through the objects, the entire mesh cache cannot be updated in one shot. - mmat = rasMesh->GetMeshMaterial(m); - - slot = mmat->m_baseslot; - for(slot->begin(it); !slot->end(it); slot->next(it)) - { - int index = 0; - for(i=it.startvertex; isetSoftBodyIndex(0); - btScalar maxDistSqr = 1e30; - btSoftBody::tNodeArray& nodes(psb->m_nodes); - btVector3 xyz = btVector3(vertex->getXYZ()[0],vertex->getXYZ()[1],vertex->getXYZ()[2]); - for (int n=0;nsetSoftBodyIndex(n); - } - } - } - } - } - } - } + hlib.ReleaseResult(hres); @@ -285,7 +235,9 @@ void CcdPhysicsController::CreateRigidbody() } else { - /* + + btSoftBodyWorldInfo& sbi= softDynaWorld->getWorldInfo(); + if (m_cci.m_collisionShape->getShapeType() ==SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) { btScaledBvhTriangleMeshShape* scaledtrimeshshape = (btScaledBvhTriangleMeshShape*) m_cci.m_collisionShape; @@ -328,16 +280,15 @@ void CcdPhysicsController::CreateRigidbody() //psb = btSoftBodyHelpers::CreateFromTriMesh(sbi,&pts[0].getX(),triangles,numtriangles); } - */ } - - m_softbodyMappingDone = true; + + m_object = psb; //psb->m_cfg.collisions = btSoftBody::fCollision::SDF_RS;//btSoftBody::fCollision::CL_SS+ btSoftBody::fCollision::CL_RS; - psb->m_cfg.collisions = btSoftBody::fCollision::SDF_RS + btSoftBody::fCollision::CL_SS; + psb->m_cfg.collisions = btSoftBody::fCollision::SDF_RS + btSoftBody::fCollision::VF_SS;//CL_SS; //psb->m_cfg.collisions = btSoftBody::fCollision::CL_SS + btSoftBody::fCollision::CL_RS; //btSoftBody::Material* pm=psb->appendMaterial(); @@ -352,10 +303,10 @@ void CcdPhysicsController::CreateRigidbody() //pm->m_kAST = 0.01f; //pm->m_kVST = 0.001f; psb->generateBendingConstraints(2,pm); - //psb->m_cfg.piterations = 4; - //psb->m_cfg.viterations = 4; - //psb->m_cfg.diterations = 4; - //psb->m_cfg.citerations = 4; + psb->m_cfg.piterations = 4; + psb->m_cfg.viterations = 4; + psb->m_cfg.diterations = 4; + psb->m_cfg.citerations = 4; if (m_cci.m_gamesoftFlag & 2)//OB_SB_GOAL) { psb->setPose(false,true);// @@ -365,7 +316,7 @@ void CcdPhysicsController::CreateRigidbody() } psb->m_cfg.kDF = 0.5; - psb->m_cfg.kMT = 0.05; + //psb->m_cfg.kMT = 0.05; psb->m_cfg.piterations = 5; psb->m_cfg.piterations = 5; @@ -392,8 +343,72 @@ void CcdPhysicsController::CreateRigidbody() //psb->m_materials[0]->m_kLST = 0.1+(i/(btScalar)(n-1))*0.9; psb->setTotalMass(m_cci.m_mass); - psb->generateClusters(8);//(64); + psb->generateClusters(64); psb->setCollisionFlags(0); + + + + + + ///create a mapping between graphics mesh vertices and soft body vertices + { + RAS_MeshObject* rasMesh= GetShapeInfo()->GetMesh(); + + if (rasMesh && !m_softbodyMappingDone) + { + + //printf("apply\n"); + RAS_MeshSlot::iterator it; + RAS_MeshMaterial *mmat; + RAS_MeshSlot *slot; + size_t i; + + //for each material + for (int m=0;mNumMaterials();m++) + { + // The vertex cache can only be updated for this deformer: + // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object) + // share the same mesh (=the same cache). As the rendering is done per polymaterial + // cycling through the objects, the entire mesh cache cannot be updated in one shot. + mmat = rasMesh->GetMeshMaterial(m); + + slot = mmat->m_baseslot; + for(slot->begin(it); !slot->end(it); slot->next(it)) + { + int index = 0; + for(i=it.startvertex; isetSoftBodyIndex(0); + btScalar maxDistSqr = 1e30; + btSoftBody::tNodeArray& nodes(psb->m_nodes); + btVector3 xyz = btVector3(vertex->getXYZ()[0],vertex->getXYZ()[1],vertex->getXYZ()[2]); + for (int n=0;nsetSoftBodyIndex(n); + } + } + } + } + } + } + } + + m_softbodyMappingDone = true; + + + + + + // m_object->setCollisionShape(rbci.m_collisionShape); btTransform startTrans; @@ -1391,6 +1406,8 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() if (m_useGimpact) { collisionMeshData = new btTriangleMesh(); + + // m_vertexArray is necessarily a multiple of 3 for (std::vector::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) { @@ -1405,7 +1422,9 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() { if (!m_unscaledShape) { - collisionMeshData = new btTriangleMesh(); + collisionMeshData = new btTriangleMesh(true,false); + collisionMeshData->m_weldingThreshold = m_weldingThreshold; + // m_vertexArray is necessarily a multiple of 3 for (std::vector::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) { diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 5d35482dd46..60c734838f3 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -43,6 +43,8 @@ class btCollisionShape; class CcdShapeConstructionInfo { public: + + static CcdShapeConstructionInfo* FindMesh(RAS_MeshObject* mesh, bool polytope); CcdShapeConstructionInfo() : @@ -54,7 +56,8 @@ public: m_refCount(1), m_meshObject(NULL), m_unscaledShape(NULL), - m_useGimpact(false) + m_useGimpact(false), + m_weldingThreshold(0.f) { m_childTrans.setIdentity(); } @@ -111,6 +114,14 @@ public: // original mesh that correspond to shape triangles. // only set for concave mesh shape. + void setVertexWeldingThreshold(float threshold) + { + m_weldingThreshold = threshold; + } + float getVertexWeldingThreshold() const + { + return m_weldingThreshold; + } protected: static std::map m_meshShapeMap; int m_refCount; // this class is shared between replicas @@ -119,7 +130,9 @@ protected: btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape, // the actual shape is of type btScaledBvhTriangleMeshShape std::vector m_shapeArray; // for compound shapes - bool m_useGimpact; + bool m_useGimpact; //use gimpact for concave dynamic/moving collision detection + float m_weldingThreshold; //welding closeby vertices together can improve softbody stability etc. + }; struct CcdConstructionInfo -- cgit v1.2.3 From a349a3201ee856ea0caac2279bc2a5060a260cae Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Fri, 26 Sep 2008 08:05:18 +0000 Subject: * split collision lib into its subparts -This is to remedy long command-line troubles for scons/mingw users. Hopefully this goes ok on other platforms too :) --- extern/bullet2/src/SConscript | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript index babd4e671f6..95d34bd840d 100644 --- a/extern/bullet2/src/SConscript +++ b/extern/bullet2/src/SConscript @@ -25,8 +25,11 @@ linearmath_src = env.Glob("LinearMath/*.cpp") bulletdyn_src = env.Glob("BulletDynamics/Vehicle/*.cpp") + env.Glob("BulletDynamics/ConstraintSolver/*.cpp") + env.Glob("BulletDynamics/Dynamics/*.cpp") -collision_src = env.Glob("BulletCollision/BroadphaseCollision/*.cpp") + env.Glob("BulletCollision/CollisionDispatch/*.cpp") + env.Glob("BulletCollision/Gimpact/*.cpp") -collision_src += env.Glob("BulletCollision/CollisionShapes/*.cpp") + env.Glob("BulletCollision/NarrowPhaseCollision/*.cpp") +collision_broadphase_src = env.Glob("BulletCollision/BroadphaseCollision/*.cpp") +collision_dispatch_src = env.Glob("BulletCollision/CollisionDispatch/*.cpp") +collision_gimpact_src = env.Glob("BulletCollision/Gimpact/*.cpp") +collision_shapes_src = env.Glob("BulletCollision/CollisionShapes/*.cpp") +collision_narrowphase_src = env.Glob("BulletCollision/NarrowPhaseCollision/*.cpp") softbody_src = env.Glob("BulletSoftBody/*.cpp") @@ -34,5 +37,9 @@ incs = '. BulletCollision BulletDynamics LinearMath BulletSoftBody' env.BlenderLib ( libname = 'extern_bullet2linmath', sources=linearmath_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) env.BlenderLib ( libname = 'extern_bullet2dynamics', sources=bulletdyn_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[19, 169], compileflags=cflags ) -env.BlenderLib ( libname = 'extern_bullet2collision', sources=collision_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) +env.BlenderLib ( libname = 'extern_bullet2collision_broadphase', sources=collision_broadphase_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) +env.BlenderLib ( libname = 'extern_bullet2collision_dispatch', sources=collision_dispatch_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) +env.BlenderLib ( libname = 'extern_bullet2collision_gimpact', sources=collision_gimpact_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) +env.BlenderLib ( libname = 'extern_bullet2collision_shapes', sources=collision_shapes_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) +env.BlenderLib ( libname = 'extern_bullet2collision_narrowphase', sources=collision_narrowphase_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) env.BlenderLib ( libname = 'extern_bullet2softbody', sources=softbody_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[18,168], compileflags=cflags ) -- cgit v1.2.3 From 06a5e9b58a0c1281609ee1ddb850fc058fe56c4f Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 26 Sep 2008 08:40:35 +0000 Subject: scons/mingw linking fixes with bullet - adjusting priorities to find libs --- extern/bullet2/src/SConscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript index 95d34bd840d..719eb44325e 100644 --- a/extern/bullet2/src/SConscript +++ b/extern/bullet2/src/SConscript @@ -37,7 +37,7 @@ incs = '. BulletCollision BulletDynamics LinearMath BulletSoftBody' env.BlenderLib ( libname = 'extern_bullet2linmath', sources=linearmath_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) env.BlenderLib ( libname = 'extern_bullet2dynamics', sources=bulletdyn_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[19, 169], compileflags=cflags ) -env.BlenderLib ( libname = 'extern_bullet2collision_broadphase', sources=collision_broadphase_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) +env.BlenderLib ( libname = 'extern_bullet2collision_broadphase', sources=collision_broadphase_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[25, 170], compileflags=cflags ) env.BlenderLib ( libname = 'extern_bullet2collision_dispatch', sources=collision_dispatch_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) env.BlenderLib ( libname = 'extern_bullet2collision_gimpact', sources=collision_gimpact_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) env.BlenderLib ( libname = 'extern_bullet2collision_shapes', sources=collision_shapes_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20, 170], compileflags=cflags ) -- cgit v1.2.3