From de493dacb32744f3c8c3019557dfa48fb6032e21 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Tue, 2 Sep 2008 15:21:05 +0000 Subject: [PATCH 001/125] New physics + related branch for Nils smoke stuff, Pablos volumetrics stuff and also Bullet work (Ben) From d682dc5bd51ad2a2673bd0e93233a5ab6abbed55 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Thu, 4 Sep 2008 23:05:00 +0000 Subject: [PATCH 002/125] svn merge -c 16350 https://svn.blender.org/svnroot/bf-blender/trunk/blender --- .../bullet2/make/msvc_7_0/Bullet_vc7.vcproj | 153 ++++++++++++++++++ .../blender/blenkernel/BKE_blenkernel.vcproj | 6 + .../gameengine/ketsji/KX_ketsji.vcproj | 8 +- 3 files changed, 163 insertions(+), 4 deletions(-) diff --git a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj index 6de2fd3a2bd..225a6ead3be 100644 --- a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj +++ b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj @@ -382,6 +382,36 @@ ECHO Done + + + + + + + + + + + + + + + + + + + + @@ -394,12 +424,30 @@ ECHO Done + + + + + + + + + + + + @@ -410,6 +458,12 @@ ECHO Done + + + + @@ -482,18 +536,45 @@ ECHO Done + + + + + + + + + + + + + + + + + + @@ -534,6 +615,12 @@ ECHO Done + + + + @@ -589,6 +676,21 @@ ECHO Done + + + + + + + + + + @@ -628,6 +730,18 @@ ECHO Done + + + + + + + + @@ -731,6 +845,12 @@ ECHO Done + + + + @@ -761,12 +881,21 @@ ECHO Done + + + + + + @@ -785,6 +914,12 @@ ECHO Done + + + + @@ -827,6 +962,12 @@ ECHO Done + + + + @@ -842,6 +983,12 @@ ECHO Done + + + + + + @@ -886,6 +1036,9 @@ ECHO Done + + diff --git a/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj b/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj index 42dcc843091..69db0a95006 100644 --- a/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj +++ b/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj @@ -506,6 +506,9 @@ + + @@ -723,6 +726,9 @@ + + diff --git a/projectfiles_vc7/gameengine/ketsji/KX_ketsji.vcproj b/projectfiles_vc7/gameengine/ketsji/KX_ketsji.vcproj index 4e362faed69..a358a868143 100644 --- a/projectfiles_vc7/gameengine/ketsji/KX_ketsji.vcproj +++ b/projectfiles_vc7/gameengine/ketsji/KX_ketsji.vcproj @@ -126,7 +126,7 @@ Date: Thu, 4 Sep 2008 23:07:43 +0000 Subject: [PATCH 003/125] Partial repair of raycast system with Bullet 2.71. Still to be done: face and normal information --- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index f9242e6876f..228709999a5 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -721,17 +721,20 @@ struct FilterClosestRayResultCallback : public btCollisionWorld::ClosestRayResul { } - virtual bool NeedRayCast(btCollisionObject* object) + virtual bool needsCollision(btBroadphaseProxy* proxy0) const { + if (!(proxy0->m_collisionFilterGroup & m_collisionFilterMask)) + return false; + if (!(m_collisionFilterGroup & proxy0->m_collisionFilterMask)) + return false; + btCollisionObject* object = (btCollisionObject*)proxy0->m_clientObject; CcdPhysicsController* phyCtrl = static_cast(object->getUserPointer()); - if (phyCtrl != m_phyRayFilter.m_ignoreController) - { - return m_phyRayFilter.needBroadphaseRayCast(phyCtrl); - } - return false; + if (phyCtrl == m_phyRayFilter.m_ignoreController) + return false; + return m_phyRayFilter.needBroadphaseRayCast(phyCtrl); } - virtual float AddSingleResult( btCollisionWorld::LocalRayResult& rayResult) + virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) { CcdPhysicsController* curHit = static_cast(rayResult.m_collisionObject->getUserPointer()); // save shape information as ClosestRayResultCallback::AddSingleResult() does not do it @@ -744,8 +747,7 @@ struct FilterClosestRayResultCallback : public btCollisionWorld::ClosestRayResul m_hitTriangleShape = NULL; m_hitTriangleIndex = 0; } - bool normalInWorldspace = true; - return ClosestRayResultCallback::addSingleResult(rayResult,normalInWorldspace); + return ClosestRayResultCallback::addSingleResult(rayResult,normalInWorldSpace); } }; From dfd51ab5b6f28b4b59685cd376024b5624375faf Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 10 Sep 2008 11:38:19 +0000 Subject: [PATCH 004/125] Bugfix [#17592] Complex particle system crash --- source/blender/blenkernel/intern/particle_system.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 71dd2f64c72..077af2851a5 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -3578,7 +3578,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS pd= epart->pd; totepart= epsys->totpart; - if(pd->forcefield==PFIELD_FORCE && pd->f_strength<0.0){ + 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); for(p=0; ppd; totepart= epsys->totpart; - if(pd->forcefield==PFIELD_FORCE && pd->f_strength>0.0){ + 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); for(p=0; p Date: Wed, 10 Sep 2008 11:40:30 +0000 Subject: [PATCH 005/125] Bugfix [#12033] Cloth and Softbody don't work with Object Actions (fix pointed out by Aligorith. Ton: You might like to look over this) --- source/blender/blenkernel/intern/depsgraph.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 80f450000bb..1be0a2aafdb 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -1924,8 +1924,10 @@ static void dag_object_time_update_flags(Object *ob) } } } - else if(ob->scriptlink.totscript) ob->recalc |= OB_RECALC_OB; - else if(ob->parent) { + + if(ob->scriptlink.totscript) ob->recalc |= OB_RECALC_OB; + + if(ob->parent) { /* motion path or bone child */ if(ob->parent->type==OB_CURVE || ob->parent->type==OB_ARMATURE) ob->recalc |= OB_RECALC_OB; } @@ -1946,10 +1948,11 @@ static void dag_object_time_update_flags(Object *ob) } } } - else if(modifiers_isSoftbodyEnabled(ob)) ob->recalc |= OB_RECALC_DATA; - else if(object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA; - else if((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA; - else { + + if(object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA; + if((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA; + + { Mesh *me; Curve *cu; Lattice *lt; From fdb057ff5397c1ff957b96a17c718ffa2745539a Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 10 Sep 2008 11:42:07 +0000 Subject: [PATCH 006/125] Implement softbody function for modifier_depeends_on_time() --- source/blender/blenkernel/intern/modifier.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 936081ab94f..f71ebc76e68 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -5293,6 +5293,11 @@ static void softbodyModifier_deformVerts( sbObjectStep(ob, (float)G.scene->r.cfra, vertexCos, numVerts); } +static int softbodyModifier_dependsOnTime(ModifierData *md) +{ + return 1; +} + /* Cloth */ @@ -7580,6 +7585,7 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->flags = eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_RequiresOriginalData; mti->deformVerts = softbodyModifier_deformVerts; + mti->dependsOnTime = softbodyModifier_dependsOnTime; mti = INIT_TYPE(Cloth); mti->type = eModifierTypeType_Nonconstructive; From f5c19c2c35192a7874f7e08362fb37f8a842521c Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 10 Sep 2008 11:45:42 +0000 Subject: [PATCH 007/125] Bugfix #17495: IPO curve handles go haywire When editing IPO curve handles on a curve that belongs to a NLA-strip with repeat != 1 and 'AutoMerge Keyframes' on, the scaling correction was causing more problems than it was worth. --- source/blender/src/transform_conversions.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 0b43dac07cf..0984b2c3175 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -3942,13 +3942,10 @@ void special_aftertrans_update(TransInfo *t) if ( (G.sipo->flag & SIPO_NOTRANSKEYCULL)==0 && (cancelled == 0) ) { - if (NLA_IPO_SCALED) { - actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 0, 1); - posttrans_ipo_clean(G.sipo->ipo); - actstrip_map_ipo_keys(OBACT, G.sipo->ipo, 1, 1); - } - else - posttrans_ipo_clean(G.sipo->ipo); + /* NOTE: no need to do NLA scaling stuff here, as when there is NLA scaling, + * the transformed handles will get moved wrong (seem to match wrong repeat cycle) + */ + posttrans_ipo_clean(G.sipo->ipo); } } From a42dd1482fb0b2d861f3bc46da1236d1835fec53 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 10 Sep 2008 12:04:20 +0000 Subject: [PATCH 008/125] Bugfix: There were too many undo events being added for IPO Editor when selecting items with the mouse. Removed deselectall_editipo()'s undo push, as it was never called standalone anyway. --- source/blender/src/editipo.c | 1 + source/blender/src/editipo_mods.c | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index cd6aefdb87c..5243b12535b 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -3651,6 +3651,7 @@ void remove_doubles_ipo(void) } deselectall_editipo(); + BIF_undo_push("Remove Doubles (IPO)"); } diff --git a/source/blender/src/editipo_mods.c b/source/blender/src/editipo_mods.c index f03de1ff383..24bb111c8d1 100644 --- a/source/blender/src/editipo_mods.c +++ b/source/blender/src/editipo_mods.c @@ -237,7 +237,6 @@ void deselectall_editipo(void) } } - BIF_undo_push("(De)select all Ipo"); scrarea_queue_winredraw(curarea); } From 90272dfdad61a6de223d96ce14a4fe4c75a1347d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 10 Sep 2008 13:02:58 +0000 Subject: [PATCH 009/125] Fix for bug #8132: on Mac OS X 10.5 with Nvidia cards drawing background images and node previews goes wrong. The exact cause of that is not sure, may be a driver bug, workaround is to fall back to another slower function. --- source/blender/include/BIF_glutil.h | 1 + source/blender/src/glutil.c | 79 +++++++++++++++++++++++++---- source/blender/src/mywindow.c | 12 ----- 3 files changed, 70 insertions(+), 22 deletions(-) diff --git a/source/blender/include/BIF_glutil.h b/source/blender/include/BIF_glutil.h index f530e7ba8d0..ed9096549ca 100644 --- a/source/blender/include/BIF_glutil.h +++ b/source/blender/include/BIF_glutil.h @@ -204,6 +204,7 @@ void bglVertex2fv(float *vec); /* intel gfx cards frontbuffer problem */ void bglFlush(void); int is_a_really_crappy_intel_card(void); +int is_a_really_crappy_nvidia_card(void); void set_inverted_drawing(int enable); diff --git a/source/blender/src/glutil.c b/source/blender/src/glutil.c index c4a7b32bf8c..69e3d4c7aac 100644 --- a/source/blender/src/glutil.c +++ b/source/blender/src/glutil.c @@ -290,17 +290,66 @@ static int get_cached_work_texture(int *w_r, int *h_r) return texid; } +#define FTOCHAR(val) val<=0.0f?0: (val>=1.0f?255: (char)(255.0f*val)) void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, void *rect) { - unsigned char *uc_rect= (unsigned char*) rect; - float *f_rect= (float *)rect; - float xzoom= glaGetOneFloat(GL_ZOOM_X), yzoom= glaGetOneFloat(GL_ZOOM_Y); - int ltexid= glaGetOneInteger(GL_TEXTURE_2D); - int lrowlength= glaGetOneInteger(GL_UNPACK_ROW_LENGTH); - int subpart_x, subpart_y, tex_w, tex_h; - int texid= get_cached_work_texture(&tex_w, &tex_h); - int nsubparts_x= (img_w+(tex_w-1))/tex_w; - int nsubparts_y= (img_h+(tex_h-1))/tex_h; + float *f_rect; + float xzoom, yzoom; + unsigned char *uc_rect; + int ltexid, lrowlength, texid, tex_w, tex_h; + int subpart_x, subpart_y, nsubparts_x, nsubparts_y; + + uc_rect= (unsigned char*) rect; + f_rect= (float *)rect; + +#ifdef __APPLE__ + /* On Nvidia, Mac OS X 10.5 this function doesn't work correct and + * can crash even, use glDrawPixels instead of textures then */ + if(is_a_really_crappy_nvidia_card()) { + float col[4], modcol[4]; + unsigned char *srect = rect; + int a; + + /* modulate with current color */ + glGetFloatv(GL_CURRENT_COLOR, col); + if(col[0]!=1.0f || col[1]!=1.0f ||col[2]!=1.0f ||col[3]!=1.0f) { + srect = MEM_callocN(4*img_w*img_h, "glDrawPixelsTexSafe"); + for(a=0; a=1.0f?255: (char)(255.0f*val)) void glaDrawPixelsSafe_to32(float fx, float fy, int img_w, int img_h, int row_w, float *rectf) { float *rf; @@ -717,6 +765,17 @@ int is_a_really_crappy_intel_card(void) return well_is_it; } +int is_a_really_crappy_nvidia_card(void) +{ + static int well_is_it= -1; + + /* Do you understand the implication? Do you? */ + if (well_is_it==-1) + well_is_it= (strcmp((char*) glGetString(GL_VENDOR), "NVIDIA Corporation") == 0); + + return well_is_it; +} + void bglFlush(void) { glFlush(); diff --git a/source/blender/src/mywindow.c b/source/blender/src/mywindow.c index cb8d233c341..6166ab18766 100644 --- a/source/blender/src/mywindow.c +++ b/source/blender/src/mywindow.c @@ -604,18 +604,6 @@ int framebuffer_to_index(unsigned int col) /* ********** END MY WINDOW ************** */ -#ifdef WIN32 -static int is_a_really_crappy_nvidia_card(void) { - static int well_is_it= -1; - - /* Do you understand the implication? Do you? */ - if (well_is_it==-1) - well_is_it= (strcmp((char*) glGetString(GL_VENDOR), "NVIDIA Corporation") == 0); - - return well_is_it; -} -#endif - void myswapbuffers(void) { ScrArea *sa; From bd518b8de6702ab1e276f7513bea735cee9417ef Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Wed, 10 Sep 2008 15:07:20 +0000 Subject: [PATCH 010/125] This is patch: [#15135] imbuf DDS support: sync to nvidia texture tools revision 602 + fix for ATI2 compressed normal maps It just updates the dds stuff. Provided by Amorilia Kent --- .../blender/imbuf/intern/dds/ColorBlock.cpp | 37 ++- source/blender/imbuf/intern/dds/ColorBlock.h | 2 + .../imbuf/intern/dds/DirectDrawSurface.cpp | 307 +++++++++++++++--- .../imbuf/intern/dds/DirectDrawSurface.h | 4 + source/blender/imbuf/intern/dds/dds_api.cpp | 1 + 5 files changed, 310 insertions(+), 41 deletions(-) diff --git a/source/blender/imbuf/intern/dds/ColorBlock.cpp b/source/blender/imbuf/intern/dds/ColorBlock.cpp index d298e8b5ea8..043fba9d675 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.cpp +++ b/source/blender/imbuf/intern/dds/ColorBlock.cpp @@ -53,6 +53,14 @@ ColorBlock::ColorBlock() { } +/// Init the color block from an array of colors. +ColorBlock::ColorBlock(const uint * linearImage) +{ + for(uint i = 0; i < 16; i++) { + color(i) = Color32(linearImage[i]); + } +} + /// Init the color block with the contents of the given block. ColorBlock::ColorBlock(const ColorBlock & block) { @@ -125,9 +133,36 @@ void ColorBlock::splatY() /// Returns true if the block has a single color. bool ColorBlock::isSingleColor() const { + Color32 mask(0xFF, 0xFF, 0xFF, 0x00); + uint u = m_color[0].u & mask.u; + for(int i = 1; i < 16; i++) { - if (m_color[0] != m_color[i]) + if (u != (m_color[i].u & mask.u)) + { + return false; + } + } + + return true; +} + +/// Returns true if the block has a single color, ignoring transparent pixels. +bool ColorBlock::isSingleColorNoAlpha() const +{ + Color32 c; + int i; + for(i = 0; i < 16; i++) + { + if (m_color[i].a != 0) c = m_color[i]; + } + + Color32 mask(0xFF, 0xFF, 0xFF, 0x00); + uint u = c.u & mask.u; + + for(; i < 16; i++) + { + if (u != (m_color[i].u & mask.u)) { return false; } diff --git a/source/blender/imbuf/intern/dds/ColorBlock.h b/source/blender/imbuf/intern/dds/ColorBlock.h index 141411f37af..537c17346a1 100644 --- a/source/blender/imbuf/intern/dds/ColorBlock.h +++ b/source/blender/imbuf/intern/dds/ColorBlock.h @@ -41,6 +41,7 @@ struct ColorBlock { ColorBlock(); + ColorBlock(const uint * linearImage); ColorBlock(const ColorBlock & block); ColorBlock(const Image * img, uint x, uint y); @@ -51,6 +52,7 @@ struct ColorBlock void splatY(); bool isSingleColor() const; + bool isSingleColorNoAlpha() const; uint countUniqueColors() const; Color32 averageColor() const; bool hasAlpha() const; diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index 01838281dee..0981ae88db6 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -80,6 +80,10 @@ static const uint FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B'); static const uint FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1'); static const uint FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2'); +static const uint FOURCC_A2XY = MAKEFOURCC('A', '2', 'X', 'Y'); + +static const uint FOURCC_DX10 = MAKEFOURCC('D', 'X', '1', '0'); + // 32 bit RGB formats. static const uint D3DFMT_R8G8B8 = 20; static const uint D3DFMT_A8R8G8B8 = 21; @@ -279,6 +283,144 @@ static const uint DDPF_NORMAL = 0x80000000U; // @@ Custom nv flag. D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4, }; + + const char * getDxgiFormatString(DXGI_FORMAT dxgiFormat) + { +#define CASE(format) case DXGI_FORMAT_##format: return #format + switch(dxgiFormat) + { + CASE(UNKNOWN); + + CASE(R32G32B32A32_TYPELESS); + CASE(R32G32B32A32_FLOAT); + CASE(R32G32B32A32_UINT); + CASE(R32G32B32A32_SINT); + + CASE(R32G32B32_TYPELESS); + CASE(R32G32B32_FLOAT); + CASE(R32G32B32_UINT); + CASE(R32G32B32_SINT); + + CASE(R16G16B16A16_TYPELESS); + CASE(R16G16B16A16_FLOAT); + CASE(R16G16B16A16_UNORM); + CASE(R16G16B16A16_UINT); + CASE(R16G16B16A16_SNORM); + CASE(R16G16B16A16_SINT); + + CASE(R32G32_TYPELESS); + CASE(R32G32_FLOAT); + CASE(R32G32_UINT); + CASE(R32G32_SINT); + + CASE(R32G8X24_TYPELESS); + CASE(D32_FLOAT_S8X24_UINT); + CASE(R32_FLOAT_X8X24_TYPELESS); + CASE(X32_TYPELESS_G8X24_UINT); + + CASE(R10G10B10A2_TYPELESS); + CASE(R10G10B10A2_UNORM); + CASE(R10G10B10A2_UINT); + + CASE(R11G11B10_FLOAT); + + CASE(R8G8B8A8_TYPELESS); + CASE(R8G8B8A8_UNORM); + CASE(R8G8B8A8_UNORM_SRGB); + CASE(R8G8B8A8_UINT); + CASE(R8G8B8A8_SNORM); + CASE(R8G8B8A8_SINT); + + CASE(R16G16_TYPELESS); + CASE(R16G16_FLOAT); + CASE(R16G16_UNORM); + CASE(R16G16_UINT); + CASE(R16G16_SNORM); + CASE(R16G16_SINT); + + CASE(R32_TYPELESS); + CASE(D32_FLOAT); + CASE(R32_FLOAT); + CASE(R32_UINT); + CASE(R32_SINT); + + CASE(R24G8_TYPELESS); + CASE(D24_UNORM_S8_UINT); + CASE(R24_UNORM_X8_TYPELESS); + CASE(X24_TYPELESS_G8_UINT); + + CASE(R8G8_TYPELESS); + CASE(R8G8_UNORM); + CASE(R8G8_UINT); + CASE(R8G8_SNORM); + CASE(R8G8_SINT); + + CASE(R16_TYPELESS); + CASE(R16_FLOAT); + CASE(D16_UNORM); + CASE(R16_UNORM); + CASE(R16_UINT); + CASE(R16_SNORM); + CASE(R16_SINT); + + CASE(R8_TYPELESS); + CASE(R8_UNORM); + CASE(R8_UINT); + CASE(R8_SNORM); + CASE(R8_SINT); + CASE(A8_UNORM); + + CASE(R1_UNORM); + + CASE(R9G9B9E5_SHAREDEXP); + + CASE(R8G8_B8G8_UNORM); + CASE(G8R8_G8B8_UNORM); + + CASE(BC1_TYPELESS); + CASE(BC1_UNORM); + CASE(BC1_UNORM_SRGB); + + CASE(BC2_TYPELESS); + CASE(BC2_UNORM); + CASE(BC2_UNORM_SRGB); + + CASE(BC3_TYPELESS); + CASE(BC3_UNORM); + CASE(BC3_UNORM_SRGB); + + CASE(BC4_TYPELESS); + CASE(BC4_UNORM); + CASE(BC4_SNORM); + + CASE(BC5_TYPELESS); + CASE(BC5_UNORM); + CASE(BC5_SNORM); + + CASE(B5G6R5_UNORM); + CASE(B5G5R5A1_UNORM); + CASE(B8G8R8A8_UNORM); + CASE(B8G8R8X8_UNORM); + + default: + return "UNKNOWN"; + } +#undef CASE + } + + const char * getD3d10ResourceDimensionString(D3D10_RESOURCE_DIMENSION resourceDimension) + { + switch(resourceDimension) + { + default: + case D3D10_RESOURCE_DIMENSION_UNKNOWN: return "UNKNOWN"; + case D3D10_RESOURCE_DIMENSION_BUFFER: return "BUFFER"; + case D3D10_RESOURCE_DIMENSION_TEXTURE1D: return "TEXTURE1D"; + case D3D10_RESOURCE_DIMENSION_TEXTURE2D: return "TEXTURE2D"; + case D3D10_RESOURCE_DIMENSION_TEXTURE3D: return "TEXTURE3D"; + } + } + /*** implementation ***/ void mem_read(Stream & mem, DDSPixelFormat & pf) @@ -451,7 +593,16 @@ void DDSHeader::setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3) // set fourcc pixel format. this->pf.flags = DDPF_FOURCC; this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3); - this->pf.bitcount = 0; + + if (this->pf.fourcc == FOURCC_ATI2) + { + this->pf.bitcount = FOURCC_A2XY; + } + else + { + this->pf.bitcount = 0; + } + this->pf.rmask = 0; this->pf.gmask = 0; this->pf.bmask = 0; @@ -508,7 +659,8 @@ void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask void DDSHeader::setDX10Format(uint format) { - this->pf.flags = 0; + //this->pf.flags = 0; + this->pf.fourcc = FOURCC_DX10; this->header10.dxgiFormat = format; } @@ -520,12 +672,18 @@ void DDSHeader::setNormalFlag(bool b) bool DDSHeader::hasDX10Header() const { - return this->pf.flags == 0; + return this->pf.fourcc == FOURCC_DX10; // @@ This is according to AMD + //return this->pf.flags == 0; // @@ This is according to MS } DirectDrawSurface::DirectDrawSurface(unsigned char *mem, uint size) : stream(mem, size), header() { mem_read(stream, header); + + // some ATI2 compressed normal maps do not have their + // normal flag set, so force it here (the original nvtt don't do + // this, but the decompressor has a -forcenormal flag) + if (header.pf.fourcc == FOURCC_ATI2) header.setNormalFlag(true); } DirectDrawSurface::~DirectDrawSurface() @@ -539,7 +697,7 @@ bool DirectDrawSurface::isValid() const return false; } - const uint required = (DDSD_WIDTH|DDSD_HEIGHT|DDSD_CAPS|DDSD_PIXELFORMAT); + const uint required = (DDSD_WIDTH|DDSD_HEIGHT/*|DDSD_CAPS|DDSD_PIXELFORMAT*/); if( (header.flags & required) != required ) { return false; } @@ -560,40 +718,46 @@ bool DirectDrawSurface::isValid() const bool DirectDrawSurface::isSupported() const { - if (header.pf.flags & DDPF_FOURCC) + if (header.hasDX10Header()) { - if (header.pf.fourcc != FOURCC_DXT1 && - header.pf.fourcc != FOURCC_DXT2 && - header.pf.fourcc != FOURCC_DXT3 && - header.pf.fourcc != FOURCC_DXT4 && - header.pf.fourcc != FOURCC_DXT5 && - header.pf.fourcc != FOURCC_RXGB && - header.pf.fourcc != FOURCC_ATI1 && - header.pf.fourcc != FOURCC_ATI2) - { - // Unknown fourcc code. - return false; - } - } - else if (header.pf.flags & DDPF_RGB) - { - // All RGB formats are supported now. } else { - return false; - } + if (header.pf.flags & DDPF_FOURCC) + { + if (header.pf.fourcc != FOURCC_DXT1 && + header.pf.fourcc != FOURCC_DXT2 && + header.pf.fourcc != FOURCC_DXT3 && + header.pf.fourcc != FOURCC_DXT4 && + header.pf.fourcc != FOURCC_DXT5 && + header.pf.fourcc != FOURCC_RXGB && + header.pf.fourcc != FOURCC_ATI1 && + header.pf.fourcc != FOURCC_ATI2) + { + // Unknown fourcc code. + return false; + } + } + else if (header.pf.flags & DDPF_RGB) + { + // All RGB formats are supported now. + } + else + { + return false; + } + + if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) + { + // Cubemaps must contain all faces. + return false; + } - if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES) - { - // Cubemaps must contain all faces. - return false; - } - - if (isTexture3D()) - { - // @@ 3D textures not supported yet. - return false; + if (isTexture3D()) + { + // @@ 3D textures not supported yet. + return false; + } } return true; @@ -641,14 +805,37 @@ bool DirectDrawSurface::hasAlpha() const } } +bool DirectDrawSurface::isTexture1D() const +{ + if (header.hasDX10Header()) + { + return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE1D; + } + return false; +} + bool DirectDrawSurface::isTexture2D() const { - return !isTexture3D() && !isTextureCube(); + if (header.hasDX10Header()) + { + return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE2D; + } + else + { + return !isTexture3D() && !isTextureCube(); + } } bool DirectDrawSurface::isTexture3D() const { + if (header.hasDX10Header()) + { + return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D; + } + else + { return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0; + } } bool DirectDrawSurface::isTextureCube() const @@ -656,6 +843,11 @@ bool DirectDrawSurface::isTextureCube() const return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0; } +void DirectDrawSurface::setNormalFlag(bool b) +{ + header.setNormalFlag(b); +} + void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap) { stream.seek(offset(face, mipmap)); @@ -709,7 +901,13 @@ void DirectDrawSurface::readLinearImage(Image * img) return; } - if (header.pf.amask != 0) + // set image format: RGB or ARGB + // alpha channel exists if and only if the alpha mask is non-zero + if (header.pf.amask == 0) + { + img->setFormat(Image::Format_RGB); + } + else { img->setFormat(Image::Format_ARGB); } @@ -735,6 +933,20 @@ void DirectDrawSurface::readLinearImage(Image * img) void DirectDrawSurface::readBlockImage(Image * img) { + + // set image format: RGB or ARGB + if (header.pf.fourcc == FOURCC_RXGB || + header.pf.fourcc == FOURCC_ATI1 || + header.pf.fourcc == FOURCC_ATI2 || + header.pf.flags & DDPF_NORMAL) + { + img->setFormat(Image::Format_RGB); + } + else + { + img->setFormat(Image::Format_ARGB); + } + const uint w = img->width(); const uint h = img->height(); @@ -971,8 +1183,23 @@ void DirectDrawSurface::printInfo() const if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n"); if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n"); - printf("\tFourCC: '%c%c%c%c'\n", ((header.pf.fourcc >> 0) & 0xFF), ((header.pf.fourcc >> 8) & 0xFF), ((header.pf.fourcc >> 16) & 0xFF), ((header.pf.fourcc >> 24) & 0xFF)); - printf("\tBit count: %d\n", header.pf.bitcount); + printf("\tFourCC: '%c%c%c%c'\n", + ((header.pf.fourcc >> 0) & 0xFF), + ((header.pf.fourcc >> 8) & 0xFF), + ((header.pf.fourcc >> 16) & 0xFF), + ((header.pf.fourcc >> 24) & 0xFF)); + if ((header.pf.fourcc & DDPF_FOURCC) && (header.pf.bitcount != 0)) + { + printf("\tSwizzle: '%c%c%c%c'\n", + (header.pf.bitcount >> 0) & 0xFF, + (header.pf.bitcount >> 8) & 0xFF, + (header.pf.bitcount >> 16) & 0xFF, + (header.pf.bitcount >> 24) & 0xFF); + } + else + { + printf("\tBit count: %d\n", header.pf.bitcount); + } printf("\tRed mask: 0x%.8X\n", header.pf.rmask); printf("\tGreen mask: 0x%.8X\n", header.pf.gmask); printf("\tBlue mask: 0x%.8X\n", header.pf.bmask); @@ -1003,11 +1230,11 @@ void DirectDrawSurface::printInfo() const printf("\tCaps 3: 0x%.8X\n", header.caps.caps3); printf("\tCaps 4: 0x%.8X\n", header.caps.caps4); - if (header.pf.flags == 0) + if (header.hasDX10Header()) { printf("DX10 Header:\n"); - printf("\tDXGI Format: %u\n", header.header10.dxgiFormat); - printf("\tResource dimension: %u\n", header.header10.resourceDimension); + printf("\tDXGI Format: %u (%s)\n", header.header10.dxgiFormat, getDxgiFormatString((DXGI_FORMAT)header.header10.dxgiFormat)); + printf("\tResource dimension: %u (%s)\n", header.header10.resourceDimension, getD3d10ResourceDimensionString((D3D10_RESOURCE_DIMENSION)header.header10.resourceDimension)); printf("\tMisc flag: %u\n", header.header10.miscFlag); printf("\tArray size: %u\n", header.header10.arraySize); } diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.h b/source/blender/imbuf/intern/dds/DirectDrawSurface.h index d8abfc69167..28fcc95fe83 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.h +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.h @@ -142,9 +142,13 @@ public: uint width() const; uint height() const; uint depth() const; + bool isTexture1D() const; bool isTexture2D() const; bool isTexture3D() const; bool isTextureCube() const; + + void setNormalFlag(bool b); + bool hasAlpha() const; /* false for DXT1, true for all other DXTs */ void mipmap(Image * img, uint f, uint m); diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index b41b940dca7..cf2f6c16d08 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -94,6 +94,7 @@ struct ImBuf *imb_load_dds(unsigned char *mem, int size, int flags) } /* convert DDS into ImBuf */ + // TODO use the image RGB or RGBA tag to determine the bits per pixel if (dds.hasAlpha()) bits_per_pixel = 32; else bits_per_pixel = 24; ibuf = IMB_allocImBuf(dds.width(), dds.height(), bits_per_pixel, 0, 0); From 3bf182c4b42d38c99e855232cb3d79fca69d2daa Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 10 Sep 2008 15:25:06 +0000 Subject: [PATCH 011/125] Bugfix for [#17561] when i try to change the particle to hair I cant choose group or object as viz; Bugfix for mat[4][4] equal to zero resulting in no duplis --> Important: Janne could you check that fixes? --- source/blender/blenkernel/intern/anim.c | 6 ++++++ source/blender/blenkernel/intern/particle.c | 9 ++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index e2ce4b9f6f3..ceb0e132ff9 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -783,6 +783,10 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ hair= (totchild == 0 || psys->childcache) && psys->pathcache; if(!hair) return; + + /* we use cache, update totchild according to cached data */ + totchild = psys->totchildcache; + totpart = psys->totcached; } psys->lattice = psys_get_lattice(par, psys); @@ -865,6 +869,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Object *par, float par_ } VECCOPY(pamat[3], cache->co); + pamat[3][3]= 1.0f; + } else if(step_nbr) { /* other keys */ diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 15d6f71073f..72b36b312ff 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3866,14 +3866,9 @@ void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSys Mat4MulMat4(mat, obrotmat, qmat); } else { - Crossf(side, nor, vec); - Normalize(side); - Crossf(nor, vec, side); - + Normalize(nor); Mat4One(mat); - VECCOPY(mat[0], vec); - VECCOPY(mat[1], side); - VECCOPY(mat[2], nor); + VECCOPY(mat[2], nor); // mat[2] is normal/direction } *scale= len; From 9e675e547e6d47c5ddf93c0e708579e0c5610564 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Wed, 10 Sep 2008 15:51:10 +0000 Subject: [PATCH 012/125] Bugfix [#17594] separated mesh crash --- source/blender/blenkernel/intern/subsurf_ccg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index d7e9fd556b6..e6797186b53 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -980,7 +980,7 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv) memset(mv, 0, sizeof(*mv)); - if(vertNum < ccgdm->edgeMap[0].startVert) { + if((vertNum < ccgdm->edgeMap[0].startVert) && (ccgSubSurf_getNumFaces(ss) > 0)) { /* this vert comes from face data */ int lastface = ccgSubSurf_getNumFaces(ss) - 1; CCGFace *f; @@ -1021,7 +1021,7 @@ static void ccgDM_getFinalVert(DerivedMesh *dm, int vertNum, MVert *mv) x = offset % gridSideVerts + 1; VecCopyf(mv->co, ccgSubSurf_getFaceGridData(ss, f, grid, x, y)); } - } else if(vertNum < ccgdm->vertMap[0].startVert) { + } else if((vertNum < ccgdm->vertMap[0].startVert) && (ccgSubSurf_getNumEdges(ss) > 0)) { /* this vert comes from edge data */ CCGEdge *e; int lastedge = ccgSubSurf_getNumEdges(ss) - 1; From 08591412381db4056c268ff3889fb45966de90ec Mon Sep 17 00:00:00 2001 From: Ken Hughes Date: Wed, 10 Sep 2008 21:37:22 +0000 Subject: [PATCH 013/125] Scripts ------- Removed empty parenthesis from class definitions, causes a syntax error in Python 2.4 (reported by Sanne on IRC, thanks!) --- release/scripts/bpymodules/BPyTextPlugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release/scripts/bpymodules/BPyTextPlugin.py b/release/scripts/bpymodules/BPyTextPlugin.py index 5e5c9f55e53..cd5a085de37 100644 --- a/release/scripts/bpymodules/BPyTextPlugin.py +++ b/release/scripts/bpymodules/BPyTextPlugin.py @@ -20,7 +20,7 @@ from Blender.sys import time from tokenize import generate_tokens, TokenError, \ COMMENT, DEDENT, INDENT, NAME, NEWLINE, NL, STRING, NUMBER -class Definition(): +class Definition: """Describes a definition or defined object through its name, line number and docstring. This is the base class for definition based descriptors. """ @@ -30,7 +30,7 @@ class Definition(): self.lineno = lineno self.doc = doc -class ScriptDesc(): +class ScriptDesc: """Describes a script through lists of further descriptor objects (classes, defs, vars) and dictionaries to built-in types (imports). If a script has not been fully parsed, its incomplete flag will be set. The time of the last From dca6bd87efd2037f070fa9694e6a8e738cb4bb2c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 10 Sep 2008 22:49:11 +0000 Subject: [PATCH 014/125] removed debug print --- source/gameengine/GamePlayer/ghost/GPG_Application.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 3d9ae66c9ea..f35e2894f65 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -745,7 +745,8 @@ void GPG_Application::stopEngine() #endif if (pyGlobalDictMarshal) { m_pyGlobalDictString_Length = PyString_Size(pyGlobalDictMarshal); - PyObject_Print(pyGlobalDictMarshal, stderr, 0); + // for testing only + // PyObject_Print(pyGlobalDictMarshal, stderr, 0); m_pyGlobalDictString = static_cast (malloc(m_pyGlobalDictString_Length)); memcpy(m_pyGlobalDictString, PyString_AsString(pyGlobalDictMarshal), m_pyGlobalDictString_Length); } else { From 9d7c56a7f2d96f6740a79b6538615d0af534cd90 Mon Sep 17 00:00:00 2001 From: Ken Hughes Date: Wed, 10 Sep 2008 23:22:12 +0000 Subject: [PATCH 015/125] Tools --------- Fix user counting for particles. id.us was not being decremented when using the browser to replace current particle system. --- source/blender/src/buttons_object.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 0f968a7c60c..bb2beaae820 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -2943,7 +2943,8 @@ void do_effects_panels(unsigned short event) psmd= (ParticleSystemModifierData*) md; psmd->psys=psys; BLI_addtail(&ob->modifiers, md); - } + } else + id->us--; idtest->us++; psys->part=(ParticleSettings*)idtest; From 2af7083d75dbb52fe6405db76b2a472b07850341 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 11 Sep 2008 01:51:45 +0000 Subject: [PATCH 016/125] BPY api addition material.freeNodes() - use to cleanup apricot files, since there is no way to remove a node tree via the UI, unused materials and duplicate images were hanging around. buttons_logic - gave the name a but more room then the controller type, better for documentation screenshots. --- source/blender/python/api2_2x/Material.c | 20 ++++++++++++++++++- source/blender/python/api2_2x/doc/Material.py | 7 +++++++ source/blender/src/buttons_logic.c | 8 ++++---- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/source/blender/python/api2_2x/Material.c b/source/blender/python/api2_2x/Material.c index e32b87da240..82fb733c7ea 100644 --- a/source/blender/python/api2_2x/Material.c +++ b/source/blender/python/api2_2x/Material.c @@ -649,7 +649,7 @@ static PyObject *Material_insertIpoKey( BPy_Material * self, PyObject * args ); static PyObject *Material_getColorband( BPy_Material * self, void * type); int Material_setColorband( BPy_Material * self, PyObject * value, void * type); static PyObject *Material_copy( BPy_Material * self ); - +static PyObject *Material_freeNodes( BPy_Material * self ); /*****************************************************************************/ /* Python BPy_Material methods table: */ @@ -887,6 +887,8 @@ static PyMethodDef BPy_Material_methods[] = { "() - Return a copy of the material."}, {"copy", ( PyCFunction ) Material_copy, METH_NOARGS, "() - Return a copy of the material."}, + {"freeNodes", ( PyCFunction ) Material_freeNodes, METH_NOARGS, + "() - Free this materials nodes."}, {NULL, NULL, 0, NULL} }; @@ -2588,6 +2590,22 @@ static PyObject *Material_copy( BPy_Material * self ) return ( PyObject * ) pymat; } +/* mat.freeNodes() */ +static PyObject *Material_freeNodes( BPy_Material * self ) +{ + if (self->material->nodetree) { + if(self->material->nodetree) { + ntreeFreeTree(self->material->nodetree); + MEM_freeN(self->material->nodetree); + } + self->material->nodetree = NULL; + self->material->use_nodes = 0; + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + /* mat_a==mat_b or mat_a!=mat_b*/ static int Material_compare( BPy_Material * a, BPy_Material * b ) { diff --git a/source/blender/python/api2_2x/doc/Material.py b/source/blender/python/api2_2x/doc/Material.py index 05497cf551c..8d45449762c 100644 --- a/source/blender/python/api2_2x/doc/Material.py +++ b/source/blender/python/api2_2x/doc/Material.py @@ -1087,5 +1087,12 @@ class Material: @return: a copy of this material """ + def freeNodes (): + """ + Removes the node tree from this material. + @rtype: bool + @return: true if nodes were freed from this material. + """ + import id_generics Material.__doc__ += id_generics.attributes diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 934ff9e008a..4f704ef5ab0 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -3298,8 +3298,8 @@ void logic_buts(void) if(cont->flag & CONT_SHOW) { cont->otype= cont->type; - uiDefButS(block, MENU, B_CHANGE_CONT, controller_pup(),(short)(xco+22), yco, 100, 19, &cont->type, 0, 0, 0, 0, "Controller type"); - but= uiDefBut(block, TEX, 1, "", (short)(xco+122), yco, (short)(width-166), 19, cont->name, 0, 31, 0, 0, "Controller name"); + uiDefButS(block, MENU, B_CHANGE_CONT, controller_pup(),(short)(xco+22), yco, 70, 19, &cont->type, 0, 0, 0, 0, "Controller type"); + but= uiDefBut(block, TEX, 1, "", (short)(xco+92), yco, (short)(width-136), 19, cont->name, 0, 31, 0, 0, "Controller name"); uiButSetFunc(but, make_unique_prop_names_cb, cont->name, (void*) 0); ycoo= yco; @@ -3309,9 +3309,9 @@ void logic_buts(void) else { cpack(0x999999); glRecti(xco+22, yco, xco+width-22,yco+19); - but= uiDefBut(block, LABEL, 0, controller_name(cont->type), (short)(xco+22), yco, 100, 19, cont, 0, 0, 0, 0, "Controller type"); + but= uiDefBut(block, LABEL, 0, controller_name(cont->type), (short)(xco+22), yco, 70, 19, cont, 0, 0, 0, 0, "Controller type"); uiButSetFunc(but, sca_move_controller, cont, NULL); - but= uiDefBut(block, LABEL, 0, cont->name,(short)(xco+122), yco,(short)(width-166), 19, cont, 0, 0, 0, 0, "Controller name"); + but= uiDefBut(block, LABEL, 0, cont->name,(short)(xco+92), yco,(short)(width-136), 19, cont, 0, 0, 0, 0, "Controller name"); uiButSetFunc(but, sca_move_controller, cont, NULL); ycoo= yco; } From 7b98b5d34ee5b8b383a97d1a83cc87d6666fa5ef Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 11 Sep 2008 06:17:21 +0000 Subject: [PATCH 017/125] Compiler warning fixes (mingw) --- source/blender/blenkernel/intern/particle.c | 2 +- source/blender/python/api2_2x/Material.c | 1 + source/blender/src/editmesh_tools.c | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 72b36b312ff..db3576f0c50 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3841,7 +3841,7 @@ void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemMo void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale) { - float loc[3], nor[3], vec[3], side[3], len, obrotmat[4][4], qmat[4][4]; + float loc[3], nor[3], vec[3], len, obrotmat[4][4], qmat[4][4]; float xvec[3] = {-1.0, 0.0, 0.0}, q[4]; VecSubf(vec, (cache+cache->steps-1)->co, cache->co); diff --git a/source/blender/python/api2_2x/Material.c b/source/blender/python/api2_2x/Material.c index 82fb733c7ea..80e4d8fce11 100644 --- a/source/blender/python/api2_2x/Material.c +++ b/source/blender/python/api2_2x/Material.c @@ -37,6 +37,7 @@ #include "BKE_library.h" #include "BKE_material.h" #include "BKE_texture.h" +#include "BKE_node.h" #include "BKE_idprop.h" #include "BKE_utildefines.h" /* for CLAMP */ #include "MEM_guardedalloc.h" diff --git a/source/blender/src/editmesh_tools.c b/source/blender/src/editmesh_tools.c index fe4c98aa4de..4cf3b410393 100644 --- a/source/blender/src/editmesh_tools.c +++ b/source/blender/src/editmesh_tools.c @@ -4703,10 +4703,10 @@ int EdgeSlide(short immediate, float imperc) int wasshift = 0; /* UV correction vars */ - GHash **uvarray; + GHash **uvarray= NULL; int uvlay_tot= CustomData_number_of_layers(&G.editMesh->fdata, CD_MTFACE); int uvlay_idx; - SlideUv *slideuvs, *suv, *suv_last; + SlideUv *slideuvs=NULL, *suv=NULL, *suv_last=NULL; float uv_tmp[2]; LinkNode *fuv_link; From 5eb1d5e3dcf4160b62118935c803f411b7283e62 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 11 Sep 2008 10:17:17 +0000 Subject: [PATCH 018/125] Fix for bug #17593: glsl crash using a texture node without a texture assigned. --- source/blender/blenkernel/intern/node.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 4dfe651c01f..94a21cdd5df 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2378,8 +2378,8 @@ static void gpu_from_node_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack gs[i].type= GPU_NONE; gs[i].name = ""; - gs[i].hasinput= ns[i]->hasinput; - gs[i].hasoutput= ns[i]->hasinput; + gs[i].hasinput= ns[i]->hasinput && ns[i]->data; + gs[i].hasoutput= ns[i]->hasinput && ns[i]->data; gs[i].sockettype= ns[i]->sockettype; } @@ -2393,7 +2393,7 @@ static void data_from_gpu_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack for (sock=sockets->first, i=0; sock; sock=sock->next, i++) { ns[i]->data= gs[i].link; - ns[i]->hasinput= gs[i].hasinput; + ns[i]->hasinput= gs[i].hasinput && gs[i].link; ns[i]->hasoutput= gs[i].hasoutput; ns[i]->sockettype= gs[i].sockettype; } From 695c354b61955b8521b05a3e6458cddb496316ee Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 11 Sep 2008 11:30:32 +0000 Subject: [PATCH 019/125] Fix for bug #17602: 32 bit bmp files were read with red and blue swapped. --- source/blender/imbuf/intern/bmp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c index 2aa276a5f53..141b8a985cf 100644 --- a/source/blender/imbuf/intern/bmp.c +++ b/source/blender/imbuf/intern/bmp.c @@ -164,9 +164,9 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, int size, int flags) } } else if (depth == 32) { for (i = x * y; i > 0; i--) { - rect[0] = bmp[0]; + rect[0] = bmp[2]; rect[1] = bmp[1]; - rect[2] = bmp[2]; + rect[2] = bmp[0]; rect[3] = bmp[3]; rect += 4; bmp += 4; } From 729af67742c3296ee3214c1e4981e4b689d57477 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 11 Sep 2008 13:00:54 +0000 Subject: [PATCH 020/125] Bugfix: saved game engine runtimes failed to load library .blend files with relative paths. --- source/blender/blenloader/BLO_readfile.h | 2 +- source/blender/blenloader/intern/readfile.c | 9 +++++++-- source/blender/readblenfile/intern/BLO_readblenfile.c | 2 +- source/gameengine/GamePlayer/ghost/GPG_ghost.cpp | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/source/blender/blenloader/BLO_readfile.h b/source/blender/blenloader/BLO_readfile.h index ff2a256f606..4aa2a229dcc 100644 --- a/source/blender/blenloader/BLO_readfile.h +++ b/source/blender/blenloader/BLO_readfile.h @@ -237,7 +237,7 @@ void BLO_library_append(struct SpaceFile *sfile, char *dir, int idcode); void BLO_library_append_(BlendHandle **libfiledata, struct direntry* filelist, int totfile, char *dir, char* file, short flag, int idcode); void BLO_script_library_append(BlendHandle **bh, char *dir, char *name, int idcode, short flag, struct Scene *scene); -BlendFileData* blo_read_blendafterruntime(int file, int actualsize, BlendReadError *error_r); +BlendFileData* blo_read_blendafterruntime(int file, char *name, int actualsize, BlendReadError *error_r); #ifdef __cplusplus } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 91e17c42da8..6b720851b0d 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -970,9 +970,11 @@ FileData *blo_openblenderfile(char *name, BlendReadError *error_r) } else { FileData *fd = filedata_new(); fd->gzfiledes = gzfile; - BLI_strncpy(fd->filename, name, sizeof(fd->filename)); // now only in use by library append fd->read = fd_read_gzip_from_file; + /* needed for library_append and read_libraries */ + BLI_strncpy(fd->filename, name, sizeof(fd->filename)); + return blo_decode_and_check(fd, error_r); } } @@ -9125,7 +9127,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) /* reading runtime */ -BlendFileData *blo_read_blendafterruntime(int file, int actualsize, BlendReadError *error_r) +BlendFileData *blo_read_blendafterruntime(int file, char *name, int actualsize, BlendReadError *error_r) { BlendFileData *bfd = NULL; FileData *fd = filedata_new(); @@ -9133,6 +9135,9 @@ BlendFileData *blo_read_blendafterruntime(int file, int actualsize, BlendReadErr fd->buffersize = actualsize; fd->read = fd_read_from_file; + /* needed for library_append and read_libraries */ + BLI_strncpy(fd->filename, name, sizeof(fd->filename)); + fd = blo_decode_and_check(fd, error_r); if (!fd) return NULL; diff --git a/source/blender/readblenfile/intern/BLO_readblenfile.c b/source/blender/readblenfile/intern/BLO_readblenfile.c index 6e5bf149c7a..ec71611b31d 100644 --- a/source/blender/readblenfile/intern/BLO_readblenfile.c +++ b/source/blender/readblenfile/intern/BLO_readblenfile.c @@ -159,7 +159,7 @@ blo_read_runtime( } else { //printf("starting to read runtime from %s at datastart %d\n", path, datastart); lseek(fd, datastart, SEEK_SET); - bfd = blo_read_blendafterruntime(fd, actualsize-datastart, error_r); + bfd = blo_read_blendafterruntime(fd, path, actualsize-datastart, error_r); fd= -1; // file was closed in blo_read_blendafterruntime() } diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index d44e983af89..3a9e59c3c25 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -613,7 +613,7 @@ int main(int argc, char** argv) } else { - bfd = load_game_data(argv[0], filename); + bfd = load_game_data(bprogname, filename); } //::printf("game data loaded from %s\n", filename); From 97178fecd942ec6418156ef033a67c1d1ee67539 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 11 Sep 2008 14:58:13 +0000 Subject: [PATCH 021/125] BGE message python api could return a CList type or None which makes exception checks annoying. just return an empty CList rather then None. --- .../KXNetwork/KX_NetworkMessageSensor.cpp | 68 +++++++------------ .../KXNetwork/KX_NetworkMessageSensor.h | 10 +-- 2 files changed, 28 insertions(+), 50 deletions(-) diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp index 0c66ac1fde3..a35ab8b15e8 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp @@ -196,19 +196,19 @@ PyParentObject KX_NetworkMessageSensor::Parents[] = { PyMethodDef KX_NetworkMessageSensor::Methods[] = { {"setSubjectFilterText", (PyCFunction) - KX_NetworkMessageSensor::sPySetSubjectFilterText, METH_VARARGS, + KX_NetworkMessageSensor::sPySetSubjectFilterText, METH_O, SetSubjectFilterText_doc}, {"getFrameMessageCount", (PyCFunction) - KX_NetworkMessageSensor::sPyGetFrameMessageCount, METH_VARARGS, + KX_NetworkMessageSensor::sPyGetFrameMessageCount, METH_NOARGS, GetFrameMessageCount_doc}, {"getBodies", (PyCFunction) - KX_NetworkMessageSensor::sPyGetBodies, METH_VARARGS, + KX_NetworkMessageSensor::sPyGetBodies, METH_NOARGS, GetBodies_doc}, {"getSubject", (PyCFunction) - KX_NetworkMessageSensor::sPyGetSubject, METH_VARARGS, + KX_NetworkMessageSensor::sPyGetSubject, METH_NOARGS, GetSubject_doc}, {"getSubjects", (PyCFunction) - KX_NetworkMessageSensor::sPyGetSubjects, METH_VARARGS, + KX_NetworkMessageSensor::sPyGetSubjects, METH_NOARGS, GetSubjects_doc}, {NULL,NULL} //Sentinel }; @@ -222,22 +222,16 @@ char KX_NetworkMessageSensor::SetSubjectFilterText_doc[] = "\tsetSubjectFilterText(value)\n" "\tChange the message subject text that this sensor is listening to.\n"; -PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText( - PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_NetworkMessageSensor::PySetSubjectFilterText( PyObject* self, PyObject* value) { - char* Subject; - - if (PyArg_ParseTuple(args, "s", &Subject)) - { - m_subject = Subject; - } - else { + char* Subject = PyString_AsString(value); + if (Subject==NULL) { + PyErr_SetString(PyExc_TypeError, "expected a string message"); return NULL; } - - Py_Return; + + m_subject = Subject; + Py_RETURN_NONE; } // 2. Get the number of messages received since the last frame @@ -245,10 +239,7 @@ char KX_NetworkMessageSensor::GetFrameMessageCount_doc[] = "\tgetFrameMessageCount()\n" "\tGet the number of messages received since the last frame.\n"; -PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount( - PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_NetworkMessageSensor::PyGetFrameMessageCount( PyObject* ) { return PyInt_FromLong(long(m_frame_message_count)); } @@ -258,16 +249,13 @@ char KX_NetworkMessageSensor::GetBodies_doc[] = "\tgetBodies()\n" "\tGet the list of message bodies.\n"; -PyObject* KX_NetworkMessageSensor::PyGetBodies( - PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_NetworkMessageSensor::PyGetBodies( PyObject* ) { if (m_BodyList) { return ((PyObject*) m_BodyList->AddRef()); + } else { + return ((PyObject*) new CListValue()); } - - Py_Return; } // 4. Get the message subject: field of the message sensor @@ -275,16 +263,9 @@ char KX_NetworkMessageSensor::GetSubject_doc[] = "\tgetSubject()\n" "\tGet the subject: field of the message sensor.\n"; -PyObject* KX_NetworkMessageSensor::PyGetSubject( - PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_NetworkMessageSensor::PyGetSubject( PyObject* ) { - if (m_subject) { - return PyString_FromString(m_subject); - } - - Py_Return; + return PyString_FromString(m_subject ? m_subject : ""); } // 5. Get the message subjects @@ -292,14 +273,11 @@ char KX_NetworkMessageSensor::GetSubjects_doc[] = "\tgetSubjects()\n" "\tGet list of message subjects.\n"; -PyObject* KX_NetworkMessageSensor::PyGetSubjects( - PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_NetworkMessageSensor::PyGetSubjects( PyObject* ) { if (m_SubjectList) { - return ((PyObject*) m_SubjectList->AddRef()); - } - - Py_Return; + return ((PyObject*) m_SubjectList->AddRef()); + } else { + return ((PyObject*) new CListValue()); + } } diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h index 6fd92d17be3..8cdfd6cdb5a 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h @@ -74,11 +74,11 @@ public: virtual PyObject* _getattr(const STR_String& attr); - KX_PYMETHOD_DOC(KX_NetworkMessageSensor, SetSubjectFilterText); - KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetFrameMessageCount); - KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetBodies); - KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetSubject); - KX_PYMETHOD_DOC(KX_NetworkMessageSensor, GetSubjects); + KX_PYMETHOD_DOC_O(KX_NetworkMessageSensor, SetSubjectFilterText); + KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetFrameMessageCount); + KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetBodies); + KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetSubject); + KX_PYMETHOD_DOC_NOARGS(KX_NetworkMessageSensor, GetSubjects); }; From d5839f21ab59ed212ab66c98e011c10e34dc2ac7 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Thu, 11 Sep 2008 16:37:53 +0000 Subject: [PATCH 022/125] Bugfix 12478 Border render didnt work for ANIM render. --- .../blender/render/intern/source/pipeline.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 1be65fa7134..bf2a72b4f9b 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -1889,6 +1889,7 @@ static void do_render_fields_blur_3d(Render *re) re->result->tilerect= re->disprect; /* this copying sequence could become function? */ + /* weak is: it chances disprect from border */ re->disprect.xmin= re->disprect.ymin= 0; re->disprect.xmax= re->winx; re->disprect.ymax= re->winy; @@ -2413,7 +2414,7 @@ static int is_rendering_allowed(Render *re) } /* evaluating scene options for general Blender render */ -static int render_initialize_from_scene(Render *re, Scene *scene) +static int render_initialize_from_scene(Render *re, Scene *scene, int anim) { int winx, winy; rcti disprect; @@ -2441,6 +2442,12 @@ static int render_initialize_from_scene(Render *re, Scene *scene) re->scene= scene; + /* not too nice, but it survives anim-border render */ + if(anim) { + re->disprect= disprect; + return 1; + } + /* check all scenes involved */ tag_scenes_for_render(re); @@ -2472,7 +2479,7 @@ void RE_BlenderFrame(Render *re, Scene *scene, int frame) scene->r.cfra= frame; - if(render_initialize_from_scene(re, scene)) { + if(render_initialize_from_scene(re, scene, 0)) { do_render_all_options(re); } @@ -2557,8 +2564,8 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra) bMovieHandle *mh= BKE_get_movie_handle(scene->r.imtype); int cfrao= scene->r.cfra; - /* do not call for each frame, it initializes & pops output window */ - if(!render_initialize_from_scene(re, scene)) + /* do not fully call for each frame, it initializes & pops output window */ + if(!render_initialize_from_scene(re, scene, 0)) return; /* ugly global still... is to prevent renderwin events and signal subsurfs etc to make full resol */ @@ -2586,6 +2593,10 @@ void RE_BlenderAnim(Render *re, Scene *scene, int sfra, int efra) } else { for(scene->r.cfra= sfra; scene->r.cfra<=efra; scene->r.cfra++) { char name[FILE_MAX]; + + /* only border now, todo: camera lens. (ton) */ + render_initialize_from_scene(re, scene, 1); + if (scene->r.mode & (R_NO_OVERWRITE | R_TOUCH) ) { BKE_makepicstring(name, scene->r.pic, scene->r.cfra, scene->r.imtype); } From 3ac4cffdd0b55c931924c1b95b96ec468bced186 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Thu, 11 Sep 2008 16:50:34 +0000 Subject: [PATCH 023/125] Bugfix #14033 Option for Image render "Clip" gave wrong alphas on the edge of image. --- source/blender/render/intern/source/imagetexture.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index c2d27f8f3a7..b9a2acb8b1c 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -577,10 +577,10 @@ static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float max if(texres->talpha==0) texres->ta= 1.0; if(alphaclip!=1.0) { - /* this is for later investigation, premul or not? */ - /* texres->tr*= alphaclip; */ - /* texres->tg*= alphaclip; */ - /* texres->tb*= alphaclip; */ + /* premul it all */ + texres->tr*= alphaclip; + texres->tg*= alphaclip; + texres->tb*= alphaclip; texres->ta*= alphaclip; } } From 13b0cf94d5da4cf96607ea8736fad6ae3ab68a4f Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Thu, 11 Sep 2008 20:09:07 +0000 Subject: [PATCH 024/125] Bullet patch for compound ray cast. The patch is filed in Bullet patch tracker for inclusion in later revision. If it is not included, apply manually extern/bullet2/bullet_compound_raycast.patch --- extern/bullet2/bullet_compound_raycast.patch | 39 +++++++++++++++++++ extern/bullet2/readme.txt | 5 +++ .../CollisionDispatch/btCollisionWorld.cpp | 11 +++++- 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 extern/bullet2/bullet_compound_raycast.patch diff --git a/extern/bullet2/bullet_compound_raycast.patch b/extern/bullet2/bullet_compound_raycast.patch new file mode 100644 index 00000000000..2658f7ed56e --- /dev/null +++ b/extern/bullet2/bullet_compound_raycast.patch @@ -0,0 +1,39 @@ +Index: src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +=================================================================== +--- src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp (r‚vision 16464) ++++ src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp (copie de travail) +@@ -379,12 +379,16 @@ + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); + btTransform childWorldTrans = colObjWorldTransform * childTrans; ++ // replace collision shape so that callback can determine the triangle ++ btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape(); ++ collisionObject->setCollisionShape((btCollisionShape*)childCollisionShape); + rayTestSingle(rayFromTrans,rayToTrans, + collisionObject, + childCollisionShape, + childWorldTrans, + resultCallback); +- ++ // restore ++ collisionObject->setCollisionShape(saveCollisionShape); + } + } + } +@@ -571,11 +575,16 @@ + btTransform childTrans = compoundShape->getChildTransform(i); + const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); + btTransform childWorldTrans = colObjWorldTransform * childTrans; ++ // replace collision shape so that callback can determine the triangle ++ btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape(); ++ collisionObject->setCollisionShape((btCollisionShape*)childCollisionShape); + objectQuerySingle(castShape, convexFromTrans,convexToTrans, + collisionObject, + childCollisionShape, + childWorldTrans, + resultCallback, allowedPenetration); ++ // restore ++ collisionObject->setCollisionShape(saveCollisionShape); + } + } + } diff --git a/extern/bullet2/readme.txt b/extern/bullet2/readme.txt index 4d1a4c11706..02430cb5c0e 100644 --- a/extern/bullet2/readme.txt +++ b/extern/bullet2/readme.txt @@ -1,3 +1,8 @@ +*** +Apply bullet_compound_raycast.patch if not already applied in Bullet source +This patch is needed to return correct raycast results on compound shape. +/ben + *** These files in extern/bullet2 are NOT part of the Blender build yet *** diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp index 7c2ecd6098a..2fd972a4761 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp @@ -379,12 +379,16 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra btTransform childTrans = compoundShape->getChildTransform(i); const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); btTransform childWorldTrans = colObjWorldTransform * childTrans; + // replace collision shape so that callback can determine the triangle + btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape(); + collisionObject->setCollisionShape((btCollisionShape*)childCollisionShape); rayTestSingle(rayFromTrans,rayToTrans, collisionObject, childCollisionShape, childWorldTrans, resultCallback); - + // restore + collisionObject->setCollisionShape(saveCollisionShape); } } } @@ -571,11 +575,16 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt btTransform childTrans = compoundShape->getChildTransform(i); const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); btTransform childWorldTrans = colObjWorldTransform * childTrans; + // replace collision shape so that callback can determine the triangle + btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape(); + collisionObject->setCollisionShape((btCollisionShape*)childCollisionShape); objectQuerySingle(castShape, convexFromTrans,convexToTrans, collisionObject, childCollisionShape, childWorldTrans, resultCallback, allowedPenetration); + // restore + collisionObject->setCollisionShape(saveCollisionShape); } } } From b16b0f91ec488b5e4718047503829e7eb8b757c6 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Thu, 11 Sep 2008 20:16:30 +0000 Subject: [PATCH 025/125] Repair rayCast part 2: return correct polygon information and true normal --- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 68 +++++++++++++++---- 1 file changed, 56 insertions(+), 12 deletions(-) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 0747761ea0a..6df3297ec7e 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -741,8 +741,8 @@ struct FilterClosestRayResultCallback : public btCollisionWorld::ClosestRayResul // save shape information as ClosestRayResultCallback::AddSingleResult() does not do it if (rayResult.m_localShapeInfo) { - m_hitTriangleShape = NULL;//rayResult.m_localShapeInfo->m_triangleShape; - m_hitTriangleIndex = 0;//rayResult.m_localShapeInfo->m_triangleIndex; + m_hitTriangleShape = rayResult.m_collisionObject->getCollisionShape(); + m_hitTriangleIndex = rayResult.m_localShapeInfo->m_triangleIndex; } else { m_hitTriangleShape = NULL; @@ -786,16 +786,6 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac result.m_hitPoint[1] = rayCallback.m_hitPointWorld.getY(); result.m_hitPoint[2] = rayCallback.m_hitPointWorld.getZ(); - if (rayCallback.m_hitNormalWorld.length2() > (SIMD_EPSILON*SIMD_EPSILON)) - { - rayCallback.m_hitNormalWorld.normalize(); - } else - { - rayCallback.m_hitNormalWorld.setValue(1,0,0); - } - result.m_hitNormal[0] = rayCallback.m_hitNormalWorld.getX(); - result.m_hitNormal[1] = rayCallback.m_hitNormalWorld.getY(); - result.m_hitNormal[2] = rayCallback.m_hitNormalWorld.getZ(); if (rayCallback.m_hitTriangleShape != NULL) { // identify the mesh polygon @@ -821,9 +811,63 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac { result.m_meshObject = shapeInfo->m_meshObject; result.m_polygon = shapeInfo->m_polygonIndexArray.at(rayCallback.m_hitTriangleIndex); + + // Bullet returns the normal from "outside". + // If the user requests the real normal, compute it now + if (filterCallback.m_faceNormal) + { + // this code is copied from Bullet + btVector3 triangle[3]; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + btTriangleMeshShape* triangleShape = (btTriangleMeshShape*)shape; + btStridingMeshInterface* meshInterface = triangleShape->getMeshInterface(); + + meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + 0); + + unsigned int* gfxbase = (unsigned int*)(indexbase+rayCallback.m_hitTriangleIndex*indexstride); + const btVector3& meshScaling = meshInterface->getScaling(); + for (int j=2;j>=0;j--) + { + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + + btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); + + triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + } + meshInterface->unLockReadOnlyVertexBase(0); + btVector3 triangleNormal; + triangleNormal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]); + rayCallback.m_hitNormalWorld = rayCallback.m_collisionObject->getWorldTransform().getBasis()*triangleNormal; + } } } } + if (rayCallback.m_hitNormalWorld.length2() > (SIMD_EPSILON*SIMD_EPSILON)) + { + rayCallback.m_hitNormalWorld.normalize(); + } else + { + rayCallback.m_hitNormalWorld.setValue(1,0,0); + } + result.m_hitNormal[0] = rayCallback.m_hitNormalWorld.getX(); + result.m_hitNormal[1] = rayCallback.m_hitNormalWorld.getY(); + result.m_hitNormal[2] = rayCallback.m_hitNormalWorld.getZ(); filterCallback.reportHit(&result); } From 75841bc97f82836e7af5524b79220b984da3b4f8 Mon Sep 17 00:00:00 2001 From: Ken Hughes Date: Thu, 11 Sep 2008 23:50:22 +0000 Subject: [PATCH 026/125] Python API ---------- Add description for missing parameter in Mesh.MFaceSeq.extend() documentation. --- source/blender/python/api2_2x/doc/Mesh.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/python/api2_2x/doc/Mesh.py b/source/blender/python/api2_2x/doc/Mesh.py index d463376efbe..e48f41e8f9c 100644 --- a/source/blender/python/api2_2x/doc/Mesh.py +++ b/source/blender/python/api2_2x/doc/Mesh.py @@ -636,7 +636,7 @@ class MFaceSeq: This object provides sequence and iterator access to the mesh's faces. """ - def extend(vertseq,ignoreDups=True,indexList=True): + def extend(vertseq,ignoreDups=True,indexList=True,smooth=False): """ Add zero or more faces and edges to the mesh. Faces which already exist in the mesh, or faces which contain the same vertex multiple times are From 0dea748e01dab697d2f8ac245bbd5e925cd732ce Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 12 Sep 2008 02:15:16 +0000 Subject: [PATCH 027/125] save and load configuration actuator, (option in game actuator menu) saves a marshal'd GameLogic.globalDict to the blendfile path with the blend extension replaced with bgeconf Use this in YoFrankie to save keyboard layout and graphics quality settings. --- source/blender/makesdna/DNA_actuator_types.h | 2 + source/blender/src/buttons_logic.c | 10 +-- .../Converter/KX_ConvertActuators.cpp | 10 +++ .../GamePlayer/ghost/GPG_Application.cpp | 47 ++----------- source/gameengine/Ketsji/KX_GameActuator.cpp | 66 +++++++++++++++++++ source/gameengine/Ketsji/KX_GameActuator.h | 2 + source/gameengine/Ketsji/KX_PythonInit.cpp | 65 ++++++++++++++++++ source/gameengine/Ketsji/KX_PythonInit.h | 4 ++ 8 files changed, 158 insertions(+), 48 deletions(-) diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index ca0ad06eac3..750bdf2cfff 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -445,6 +445,8 @@ typedef struct FreeCamera { #define ACT_GAME_START 1 #define ACT_GAME_RESTART 2 #define ACT_GAME_QUIT 3 +#define ACT_GAME_SAVECFG 4 +#define ACT_GAME_LOADCFG 5 /* visibilityact->flag */ /* Set means the object will become invisible */ diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 4f704ef5ab0..a87104c82de 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -2296,13 +2296,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh uiDefBut(block, TEX, 1, "File: ", xco+10, yco-44,width-20,19, &(gma->filename), 0, 63, 0, 0, "Load this file"); uiDefBut(block, TEX, 1, "Anim: ", xco+10, yco-64,width-20,19, &(gma->loadaniname), 0, 63, 0, 0, "Use this loadinganimation"); } -*/ else if (gma->type == ACT_GAME_RESTART) - { - ysize = 28; - glRects(xco, yco-ysize, xco+width, yco); - uiEmboss((float)xco, (float)yco-ysize, (float)xco+width, (float)yco, 1); - } - else if (gma->type == ACT_GAME_QUIT) +*/ else if (ELEM4(gma->type, ACT_GAME_RESTART, ACT_GAME_QUIT, ACT_GAME_SAVECFG, ACT_GAME_LOADCFG)) { ysize = 28; glRects(xco, yco-ysize, xco+width, yco); @@ -2310,7 +2304,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh } //str = "Scene %t|Load game%x0|Start loaded game%x1|Restart this game%x2|Quit this game %x3"; - str = "Scene %t|Start new game%x0|Restart this game%x2|Quit this game %x3"; + str = "Scene %t|Start new game%x0|Restart this game%x2|Quit this game %x3|Save GameLogic.globalDict %x4|Load GameLogic.globalDict %x5"; uiDefButS(block, MENU, B_REDR, str, xco+40, yco-24, (width-80), 19, &gma->type, 0.0, 0.0, 0, 0, ""); yco -= ysize; diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 3142f7652de..799506aecaa 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -876,6 +876,16 @@ void BL_ConvertActuators(char* maggiename, mode = KX_GameActuator::KX_GAME_QUIT; break; } + case ACT_GAME_SAVECFG: + { + mode = KX_GameActuator::KX_GAME_SAVECFG; + break; + } + case ACT_GAME_LOADCFG: + { + mode = KX_GameActuator::KX_GAME_LOADCFG; + break; + } default: ; /* flag error */ } diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index f35e2894f65..0287178004d 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -98,7 +98,6 @@ extern "C" #include "GHOST_IEventConsumer.h" #include "GHOST_IWindow.h" #include "GHOST_Rect.h" -#include "marshal.h" static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time); @@ -685,15 +684,7 @@ bool GPG_Application::startEngine(void) initMathutils(); /* Restore the dict */ - if (m_pyGlobalDictString) { - PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(m_pyGlobalDictString, m_pyGlobalDictString_Length); - if (pyGlobalDict) { - PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module. - } else { - PyErr_Clear(); - printf("Error could not marshall string\n"); - } - } + loadGamePythonConfig(m_pyGlobalDictString, m_pyGlobalDictString_Length); m_sceneconverter->ConvertScene( startscenename, @@ -731,36 +722,12 @@ bool GPG_Application::startEngine(void) void GPG_Application::stopEngine() { // get the python dict and convert to a string for future use - { - SetPyGlobalDictMarshal(NULL, 0); - - PyObject* gameLogic = PyImport_ImportModule("GameLogic"); - if (gameLogic) { - PyObject* pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module - if (pyGlobalDict) { -#ifdef Py_MARSHAL_VERSION - PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5 -#else - PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict ); -#endif - if (pyGlobalDictMarshal) { - m_pyGlobalDictString_Length = PyString_Size(pyGlobalDictMarshal); - // for testing only - // PyObject_Print(pyGlobalDictMarshal, stderr, 0); - m_pyGlobalDictString = static_cast (malloc(m_pyGlobalDictString_Length)); - memcpy(m_pyGlobalDictString, PyString_AsString(pyGlobalDictMarshal), m_pyGlobalDictString_Length); - } else { - printf("Error, GameLogic.globalDict could not be marshal'd\n"); - } - Py_DECREF(gameLogic); - } else { - printf("Error, GameLogic.globalDict was removed\n"); - } - } else { - printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); - } - } - + char *marshal_buffer; + m_pyGlobalDictString_Length = saveGamePythonConfig(&marshal_buffer); + if (m_pyGlobalDictString_Length) { + m_pyGlobalDictString = static_cast (malloc(m_pyGlobalDictString_Length)); + memcpy(m_pyGlobalDictString, marshal_buffer, m_pyGlobalDictString_Length); + } // when exiting the mainloop exitGamePythonScripting(); diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp index fcd32d5f4fe..91ddbbbfbc9 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.cpp +++ b/source/gameengine/Ketsji/KX_GameActuator.cpp @@ -34,6 +34,7 @@ //#include #include "KX_Scene.h" #include "KX_KetsjiEngine.h" +#include "KX_PythonInit.h" /* for config load/saving */ #ifdef HAVE_CONFIG_H #include @@ -125,6 +126,71 @@ bool KX_GameActuator::Update() } break; } + case KX_GAME_SAVECFG: + { + if (m_ketsjiengine) + { + char mashal_path[512]; + char *marshal_buffer = NULL; + int marshal_length; + FILE *fp = NULL; + + pathGamePythonConfig(mashal_path); + marshal_length = saveGamePythonConfig(&marshal_buffer); + + if (marshal_length && marshal_buffer) { + fp = fopen(mashal_path, "wb"); + if (fp) { + if (fwrite(marshal_buffer, 1, marshal_length, fp) != marshal_length) { + printf("Warning: could not write marshal data\n"); + } + fclose(fp); + } else { + printf("Warning: could not open marshal file\n"); + } + } else { + printf("Warning: could not create marshal buffer\n"); + } + } + break; + } + case KX_GAME_LOADCFG: + { + if (m_ketsjiengine) + { + char mashal_path[512]; + char *marshal_buffer; + int marshal_length; + FILE *fp = NULL; + int result; + + pathGamePythonConfig(mashal_path); + + fp = fopen(mashal_path, "rb"); + if (fp) { + // obtain file size: + fseek (fp , 0 , SEEK_END); + marshal_length = ftell(fp); + rewind(fp); + + marshal_buffer = (char*) malloc (sizeof(char)*marshal_length); + + result = fread (marshal_buffer, 1, marshal_length, fp); + + if (result == marshal_length) { + loadGamePythonConfig(marshal_buffer, marshal_length); + } else { + printf("warning: could not read all of '%s'\n", mashal_path); + } + + free(marshal_buffer); + fclose(fp); + } else { + printf("warning: could not open '%s'\n", mashal_path); + } + } + break; + } default: ; /* do nothing? this is an internal error !!! */ } diff --git a/source/gameengine/Ketsji/KX_GameActuator.h b/source/gameengine/Ketsji/KX_GameActuator.h index 8565dc46caa..bb3448995dc 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.h +++ b/source/gameengine/Ketsji/KX_GameActuator.h @@ -54,6 +54,8 @@ protected: KX_GAME_START, KX_GAME_RESTART, KX_GAME_QUIT, + KX_GAME_SAVECFG, + KX_GAME_LOADCFG, KX_GAME_MAX }; diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index eb0052d71ff..5742c530f6d 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -74,6 +74,8 @@ extern "C" { #include "Mathutils.h" // Blender.Mathutils module copied here so the blenderlayer can use. } +#include "marshal.h" /* python header for loading/saving dicts */ + #include "PHY_IPhysicsEnvironment.h" // FIXME: Enable for access to blender python modules. This is disabled because // python has dependencies on a lot of other modules and is a pain to link. @@ -1319,3 +1321,66 @@ class KX_Scene* PHY_GetActiveScene() { return gp_KetsjiScene; } + +// utility function for loading and saving the globalDict +int saveGamePythonConfig( char **marshal_buffer) +{ + int marshal_length = 0; + PyObject* gameLogic = PyImport_ImportModule("GameLogic"); + if (gameLogic) { + PyObject* pyGlobalDict = PyDict_GetItemString(PyModule_GetDict(gameLogic), "globalDict"); // Same as importing the module + if (pyGlobalDict) { +#ifdef Py_MARSHAL_VERSION + PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict, 2); // Py_MARSHAL_VERSION == 2 as of Py2.5 +#else + PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict ); +#endif + if (pyGlobalDictMarshal) { + marshal_length= PyString_Size(pyGlobalDictMarshal); + // for testing only + // PyObject_Print(pyGlobalDictMarshal, stderr, 0); + *marshal_buffer = PyString_AsString(pyGlobalDictMarshal); + } else { + printf("Error, GameLogic.globalDict could not be marshal'd\n"); + } + Py_DECREF(gameLogic); + } else { + printf("Error, GameLogic.globalDict was removed\n"); + } + } else { + printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); + } + return marshal_length; +} + +int loadGamePythonConfig(char *marshal_buffer, int marshal_length) +{ + PyObject* gameLogic = PyImport_ImportModule("GameLogic"); + /* Restore the dict */ + if (marshal_buffer) { + PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(marshal_buffer, marshal_length); + if (pyGlobalDict) { + PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module. + return 1; + } else { + PyErr_Clear(); + printf("Error could not marshall string\n"); + } + } else { + printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); + } + return 0; +} + +void pathGamePythonConfig( char *path ) +{ + int len = strlen(G.sce); + + strncpy(path, G.sce, sizeof(G.sce)); + /* replace extension */ + if (BLI_testextensie(path, ".blend")) { + strcpy(path+(len-6), ".bgeconf"); + } else { + strcpy(path+len, ".bgeconf"); + } +} diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h index 388d073c6db..28d9d72a4c3 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.h +++ b/source/gameengine/Ketsji/KX_PythonInit.h @@ -49,6 +49,10 @@ void exitGamePlayerPythonScripting(); PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level); void exitGamePythonScripting(); +void pathGamePythonConfig( char *path ); +int saveGamePythonConfig( char **marshal_buffer); +int loadGamePythonConfig(char *marshal_buffer, int marshal_length); + void PHY_SetActiveScene(class KX_Scene* scene); class KX_Scene* PHY_GetActiveScene(); #include "MT_Vector3.h" From 4335811695761dcd3031acee507b4e9a44b09bdd Mon Sep 17 00:00:00 2001 From: Ken Hughes Date: Fri, 12 Sep 2008 02:23:52 +0000 Subject: [PATCH 028/125] Python API ---------- Second and final part of MTex API changes. Added support for new attributes for MTex World objects, stricter checking of attribute types for materia/lamp/world MTex objects, setters for lamp.textures and world.textures attributes, and updated documentation. --- source/blender/python/api2_2x/Lamp.c | 75 ++++++++++- source/blender/python/api2_2x/MTex.c | 134 +++++++++++++++---- source/blender/python/api2_2x/Material.c | 7 +- source/blender/python/api2_2x/Texture.c | 6 + source/blender/python/api2_2x/World.c | 75 ++++++++++- source/blender/python/api2_2x/doc/Texture.py | 113 +++++++++------- 6 files changed, 331 insertions(+), 79 deletions(-) diff --git a/source/blender/python/api2_2x/Lamp.c b/source/blender/python/api2_2x/Lamp.c index 1b9b1041aee..122c294001b 100644 --- a/source/blender/python/api2_2x/Lamp.c +++ b/source/blender/python/api2_2x/Lamp.c @@ -34,6 +34,7 @@ #include "BKE_global.h" #include "BKE_object.h" #include "BKE_library.h" +#include "BKE_texture.h" #include "BLI_blenlib.h" #include "BIF_space.h" #include "BSE_editipo.h" @@ -44,6 +45,7 @@ #include "gen_utils.h" #include "gen_library.h" #include "BKE_utildefines.h" +#include "MEM_guardedalloc.h" /*****************************************************************************/ /* Python BPy_Lamp defaults: */ @@ -255,6 +257,7 @@ static int Lamp_setHaloInt( BPy_Lamp * self, PyObject * args ); static int Lamp_setQuad1( BPy_Lamp * self, PyObject * args ); static int Lamp_setQuad2( BPy_Lamp * self, PyObject * args ); static int Lamp_setCol( BPy_Lamp * self, PyObject * args ); +static int Lamp_setTextures( BPy_Lamp * self, PyObject * value ); static PyObject *Lamp_getScriptLinks( BPy_Lamp * self, PyObject * value ); static PyObject *Lamp_addScriptLink( BPy_Lamp * self, PyObject * args ); static PyObject *Lamp_clearScriptLinks( BPy_Lamp * self, PyObject * args ); @@ -503,7 +506,7 @@ static PyGetSetDef BPy_Lamp_getseters[] = { "Lamp color blue component", (void *)EXPP_LAMP_COMP_B}, {"textures", - (getter)Lamp_getTextures, (setter)NULL, + (getter)Lamp_getTextures, (setter)Lamp_setTextures, "The Lamp's texture list as a tuple", NULL}, {"Modes", @@ -1423,6 +1426,76 @@ static PyObject *Lamp_getTextures( BPy_Lamp * self ) return tuple; } +static int Lamp_setTextures( BPy_Lamp * self, PyObject * value ) +{ + int i; + + if( !PyList_Check( value ) && !PyTuple_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list of integers" ); + + /* don't allow more than MAX_MTEX items */ + if( PySequence_Size(value) > MAX_MTEX ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "size of sequence greater than number of allowed textures" ); + + /* get a fast sequence; in Python 2.5, this just return the original + * list or tuple and INCREFs it, so we must DECREF */ + value = PySequence_Fast( value, "" ); + + /* check the list for valid entries */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + if( item == Py_None || ( BPy_MTex_Check( item ) && + ((BPy_MTex *)item)->type == ID_LA ) ) { + continue; + } else { + Py_DECREF(value); + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list containing lamp MTex objects and NONE" ); + } + } + + /* for each MTex object, copy to this structure */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->lamp->mtex[i]; + if( item != Py_None ) { + BPy_MTex *obj = (BPy_MTex *)item; + + /* if MTex is already at this location, just skip it */ + if( obj->mtex == mtex ) continue; + + /* create a new entry if needed, otherwise update reference count + * for texture that is being replaced */ + if( !mtex ) + mtex = self->lamp->mtex[i] = add_mtex( ); + else + mtex->tex->id.us--; + + /* copy the data */ + mtex->tex = obj->mtex->tex; + id_us_plus( &mtex->tex->id ); + mtex->texco = obj->mtex->texco; + mtex->mapto = obj->mtex->mapto; + } + } + + /* now go back and free any entries now marked as None */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->lamp->mtex[i]; + if( item == Py_None && mtex ) { + mtex->tex->id.us--; + MEM_freeN( mtex ); + self->lamp->mtex[i] = NULL; + } + } + + Py_DECREF(value); + return 0; +} + /* #####DEPRECATED###### */ static PyObject *Lamp_oldsetSamples( BPy_Lamp * self, PyObject * args ) diff --git a/source/blender/python/api2_2x/MTex.c b/source/blender/python/api2_2x/MTex.c index fa7c62ac8d6..4db9715a465 100644 --- a/source/blender/python/api2_2x/MTex.c +++ b/source/blender/python/api2_2x/MTex.c @@ -22,7 +22,7 @@ * * This is a new part of Blender. * - * Contributor(s): Alex Mole, Yehoshua Sapir + * Contributor(s): Alex Mole, Yehoshua Sapir, Ken Hughes * * ***** END GPL LICENSE BLOCK ***** */ @@ -36,7 +36,8 @@ #include "gen_utils.h" #include "gen_library.h" -#include +#include "DNA_material_types.h" +#include "DNA_world_types.h" /*****************************************************************************/ /* Python BPy_MTex methods declarations: */ @@ -95,6 +96,7 @@ MTEXGETSET(ProjX) MTEXGETSET(ProjY) MTEXGETSET(ProjZ) MTEXGETSET(MapToFlag) +MTEXGETSET(WorldMapToFlag) /*****************************************************************************/ /* Python get/set methods table */ @@ -155,8 +157,14 @@ static PyGetSetDef MTex_getseters[] = { "Projection of Y axis to Texture space", NULL }, { "zproj", (getter) MTex_getProjZ, (setter) MTex_setProjZ, "Projection of Z axis to Texture space", NULL }, + + /* MapTo for Material and Lamp MTex */ + { "mtCol", (getter) MTex_getMapToFlag, (setter) MTex_setMapToFlag, "How texture maps to color", (void*) MAP_COL }, + + /* MapTo for Material MTex */ + { "mtNor", (getter) MTex_getMapToFlag, (setter) MTex_setMapToFlag, "How texture maps to normals", (void*) MAP_NORM }, { "mtCsp", (getter) MTex_getMapToFlag, (setter) MTex_setMapToFlag, @@ -183,6 +191,18 @@ static PyGetSetDef MTex_getseters[] = { "How texture maps to displacement", (void*) MAP_DISPLACE }, { "mtWarp", (getter) MTex_getMapToFlag, (setter) MTex_setMapToFlag, "How texture maps to warp", (void*) MAP_WARP }, + + /* MapTo for World MTex */ + + { "mtBlend", (getter) MTex_getWorldMapToFlag, (setter) MTex_setWorldMapToFlag, + "Texture affects color progression of background", (void*) WOMAP_BLEND }, + { "mtHoriz", (getter) MTex_getWorldMapToFlag, (setter) MTex_setWorldMapToFlag, + "Texture affects color of the horizon", (void*) WOMAP_HORIZ }, + { "mtZenUp", (getter) MTex_getWorldMapToFlag, (setter) MTex_setWorldMapToFlag, + "Texture affects color of the zenith above", (void*) WOMAP_ZENUP }, + { "mtZenDown", (getter) MTex_getWorldMapToFlag, (setter) MTex_setWorldMapToFlag, + "Texture affects color of the zenith below", (void*) WOMAP_ZENDOWN }, + { NULL, NULL, NULL, NULL, NULL } }; @@ -323,19 +343,37 @@ static int MTex_setTexCo( BPy_MTex *self, PyObject *value, void *closure) { int texco; - if( !PyInt_Check( value ) ) { + if( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "Value must be a member of Texture.TexCo dictionary" ); - } texco = PyInt_AsLong( value ) ; - if (texco != TEXCO_ORCO && texco != TEXCO_REFL && texco != TEXCO_NORM && - texco != TEXCO_GLOB && texco != TEXCO_UV && texco != TEXCO_OBJECT && - texco != TEXCO_STRESS && texco != TEXCO_TANGENT && texco != TEXCO_WINDOW && - texco != TEXCO_VIEW && texco != TEXCO_STICKY ) - return EXPP_ReturnIntError( PyExc_ValueError, - "Value must be a member of Texture.TexCo dictionary" ); + switch ( self->type ) { + case ID_MA : + if( texco != TEXCO_ORCO && texco != TEXCO_REFL && + texco != TEXCO_NORM && texco != TEXCO_GLOB && + texco != TEXCO_UV && texco != TEXCO_OBJECT && + texco != TEXCO_STRESS && texco != TEXCO_TANGENT && + texco != TEXCO_WINDOW && texco != TEXCO_VIEW && + texco != TEXCO_STICKY ) + return EXPP_ReturnIntError( PyExc_ValueError, + "Value must be a member of Texture.TexCo dictionary" ); + break; + case ID_LA : + if( texco != TEXCO_VIEW && texco != TEXCO_GLOB && + texco != TEXCO_OBJECT ) + return EXPP_ReturnIntError( PyExc_ValueError, + "Value must be a member of Texture.TexCo dictionary" ); + break; + default: /* ID_WO */ + if( texco != TEXCO_VIEW && texco != TEXCO_GLOB && + texco != TEXCO_ANGMAP && texco != TEXCO_OBJECT && + texco != TEXCO_H_SPHEREMAP && texco != TEXCO_H_TUBEMAP ) + return EXPP_ReturnIntError( PyExc_ValueError, + "Value must be a member of Texture.TexCo dictionary" ); + break; + } self->mtex->texco = (short)texco; @@ -468,18 +506,13 @@ static int MTex_setBlendMode( BPy_MTex *self, PyObject *value, void *closure) if ( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, - "Value must be member of Texture.BlendModes dictionary" ); + "Value must be member of Texture.BlendModes dictionary" ); n = PyInt_AsLong(value); -/* if (n != MTEX_BLEND && n != MTEX_MUL && n != MTEX_ADD && - n != MTEX_SUB && n != MTEX_DIV && n != MTEX_DARK && - n != MTEX_DIFF && n != MTEX_LIGHT && n != MTEX_SCREEN)*/ if (n < 0 || n > 8) - { return EXPP_ReturnIntError( PyExc_ValueError, - "Value must be member of Texture.BlendModes dictionary" ); - } + "Value must be member of Texture.BlendModes dictionary" ); self->mtex->blendtype = (short)n; @@ -675,19 +708,33 @@ static int MTex_setMapping( BPy_MTex *self, PyObject *value, void *closure) static PyObject *MTex_getFlag( BPy_MTex *self, void *closure ) { - return PyBool_FromLong( self->mtex->texflag & (GET_INT_FROM_POINTER(closure)) ); + int flag = GET_INT_FROM_POINTER(closure); + + if( self->type != ID_MA && + flag & ( MTEX_VIEWSPACE | MTEX_DUPLI_MAPTO | MTEX_OB_DUPLI_ORIG ) ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "attribute only vaild for material MTex object" ); + + return PyBool_FromLong( self->mtex->texflag & flag ); } static int MTex_setFlag( BPy_MTex *self, PyObject *value, void *closure) { + int flag = GET_INT_FROM_POINTER(closure); + + if( self->type != ID_MA && + flag & ( MTEX_VIEWSPACE | MTEX_DUPLI_MAPTO | MTEX_OB_DUPLI_ORIG ) ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "attribute only vaild for material MTex object" ); + if ( !PyBool_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, "expected a bool"); if ( value == Py_True ) - self->mtex->texflag |= GET_INT_FROM_POINTER(closure); + self->mtex->texflag |= flag; else - self->mtex->texflag &= ~(GET_INT_FROM_POINTER(closure)); + self->mtex->texflag &= ~flag; return 0; } @@ -798,9 +845,9 @@ static PyObject *MTex_getMapToFlag( BPy_MTex *self, void *closure ) { int flag = GET_INT_FROM_POINTER(closure); - if( self->type != ID_MA ) + if( self->type == ID_LA && flag != MAP_COL ) return EXPP_ReturnPyObjError( PyExc_AttributeError, - "not a material MTex object" ); + "attribute not available for a lamp MTex" ); if ( self->mtex->mapto & flag ) return PyInt_FromLong( ( self->mtex->maptoneg & flag ) ? -1 : 1 ); @@ -808,14 +855,25 @@ static PyObject *MTex_getMapToFlag( BPy_MTex *self, void *closure ) return PyInt_FromLong( 0 ); } +static PyObject *MTex_getWorldMapToFlag( BPy_MTex *self, void *closure ) +{ + int flag = GET_INT_FROM_POINTER(closure); + + if( self->type != ID_WO ) + return EXPP_ReturnPyObjError( PyExc_AttributeError, + "not a world MTex object" ); + + return PyInt_FromLong( (long)( (self->mtex->mapto & flag) != 0 ) ); +} + static int MTex_setMapToFlag( BPy_MTex *self, PyObject *value, void *closure) { int flag = GET_INT_FROM_POINTER(closure); int intVal; - if( self->type != ID_MA ) + if( self->type == ID_LA && flag != MAP_COL ) return EXPP_ReturnIntError( PyExc_AttributeError, - "not a material MTex object" ); + "attribute not available for a lamp MTex" ); if ( !PyInt_Check( value ) ) return EXPP_ReturnIntError( PyExc_TypeError, @@ -855,3 +913,31 @@ static int MTex_setMapToFlag( BPy_MTex *self, PyObject *value, void *closure) return 0; } + +static int MTex_setWorldMapToFlag( BPy_MTex *self, PyObject *value, void *closure) +{ + int flag = GET_INT_FROM_POINTER(closure); + + if( self->type != ID_WO ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "attribute only available for a world MTex" ); + + if ( !PyInt_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected an int"); + + switch( PyInt_AsLong( value ) ) { + case 0: + self->mtex->mapto &= ~flag; + break; + case 1: + self->mtex->mapto |= flag; + break; + default: + return EXPP_ReturnIntError( PyExc_ValueError, + "value for mapping must be 0 or 1" ); + } + + return 0; +} + diff --git a/source/blender/python/api2_2x/Material.c b/source/blender/python/api2_2x/Material.c index 80e4d8fce11..145629d0aaa 100644 --- a/source/blender/python/api2_2x/Material.c +++ b/source/blender/python/api2_2x/Material.c @@ -2456,10 +2456,13 @@ static int Material_setTextures( BPy_Material * self, PyObject * value ) /* check the list for valid entries */ for( i= 0; i < PySequence_Size(value) ; ++i ) { PyObject *item = PySequence_Fast_GET_ITEM( value, i ); - if( item != Py_None && !BPy_MTex_Check( item ) ) { + if( item == Py_None || ( BPy_MTex_Check( item ) && + ((BPy_MTex *)item)->type == ID_MA ) ) { + continue; + } else { Py_DECREF(value); return EXPP_ReturnIntError( PyExc_TypeError, - "expected tuple or list containing MTex objects and NONE" ); + "expected tuple or list containing material MTex objects and NONE" ); } } diff --git a/source/blender/python/api2_2x/Texture.c b/source/blender/python/api2_2x/Texture.c index cc394801d88..141b36a05d6 100644 --- a/source/blender/python/api2_2x/Texture.c +++ b/source/blender/python/api2_2x/Texture.c @@ -42,6 +42,7 @@ #include "DNA_material_types.h" #include "DNA_scene_types.h" #include "DNA_texture_types.h" +#include "DNA_world_types.h" #include "MTex.h" #include "Image.h" @@ -1142,6 +1143,11 @@ static PyObject *M_Texture_TexCoDict( void ) PyConstant_Insert(d, "STICK", PyInt_FromLong(TEXCO_STICKY)); PyConstant_Insert(d, "STRESS", PyInt_FromLong(TEXCO_STRESS)); PyConstant_Insert(d, "TANGENT", PyInt_FromLong(TEXCO_TANGENT)); + + /* World TexCo Settings */ + PyConstant_Insert(d, "ANGMAP", PyInt_FromLong(TEXCO_ANGMAP)); + PyConstant_Insert(d, "HSPHERE", PyInt_FromLong(TEXCO_H_SPHEREMAP)); + PyConstant_Insert(d, "HTUBE", PyInt_FromLong(TEXCO_H_TUBEMAP)); } return TexCo; } diff --git a/source/blender/python/api2_2x/World.c b/source/blender/python/api2_2x/World.c index 3901e8296fb..09f7baed348 100644 --- a/source/blender/python/api2_2x/World.c +++ b/source/blender/python/api2_2x/World.c @@ -47,6 +47,7 @@ #include "BKE_world.h" #include "BKE_main.h" #include "BKE_library.h" +#include "BKE_texture.h" #include "BLI_blenlib.h" #include "BSE_editipo.h" #include "BIF_space.h" @@ -55,6 +56,7 @@ #include "MTex.h" #include "gen_utils.h" #include "gen_library.h" +#include "MEM_guardedalloc.h" #define IPOKEY_ZENITH 0 #define IPOKEY_HORIZON 1 @@ -101,6 +103,7 @@ static PyObject *World_addScriptLink( BPy_World * self, PyObject * args ); static PyObject *World_clearScriptLinks( BPy_World * self, PyObject * args ); static PyObject *World_setCurrent( BPy_World * self ); static PyObject *World_getTextures( BPy_World * self ); +static int World_setTextures( BPy_World * self, PyObject * value ); static PyObject *World_copy( BPy_World * self ); @@ -252,7 +255,7 @@ static PyGetSetDef BPy_World_getseters[] = { "world mist settings", NULL}, {"ipo", (getter)World_getIpo, (setter)World_setIpo, "world ipo", NULL}, - {"textures", (getter)World_getTextures, (setter)NULL, + {"textures", (getter)World_getTextures, (setter)World_setTextures, "The World's texture list as a tuple", NULL}, {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ @@ -1058,3 +1061,73 @@ static PyObject *World_getTextures( BPy_World * self ) return tuple; } + +static int World_setTextures( BPy_World * self, PyObject * value ) +{ + int i; + + if( !PyList_Check( value ) && !PyTuple_Check( value ) ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list of integers" ); + + /* don't allow more than MAX_MTEX items */ + if( PySequence_Size(value) > MAX_MTEX ) + return EXPP_ReturnIntError( PyExc_AttributeError, + "size of sequence greater than number of allowed textures" ); + + /* get a fast sequence; in Python 2.5, this just return the original + * list or tuple and INCREFs it, so we must DECREF */ + value = PySequence_Fast( value, "" ); + + /* check the list for valid entries */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + if( item == Py_None || ( BPy_MTex_Check( item ) && + ((BPy_MTex *)item)->type == ID_WO ) ) { + continue; + } else { + Py_DECREF(value); + return EXPP_ReturnIntError( PyExc_TypeError, + "expected tuple or list containing world MTex objects and NONE" ); + } + } + + /* for each MTex object, copy to this structure */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->world->mtex[i]; + if( item != Py_None ) { + BPy_MTex *obj = (BPy_MTex *)item; + + /* if MTex is already at this location, just skip it */ + if( obj->mtex == mtex ) continue; + + /* create a new entry if needed, otherwise update reference count + * for texture that is being replaced */ + if( !mtex ) + mtex = self->world->mtex[i] = add_mtex( ); + else + mtex->tex->id.us--; + + /* copy the data */ + mtex->tex = obj->mtex->tex; + id_us_plus( &mtex->tex->id ); + mtex->texco = obj->mtex->texco; + mtex->mapto = obj->mtex->mapto; + } + } + + /* now go back and free any entries now marked as None */ + for( i= 0; i < PySequence_Size(value) ; ++i ) { + PyObject *item = PySequence_Fast_GET_ITEM( value, i ); + struct MTex *mtex = self->world->mtex[i]; + if( item == Py_None && mtex ) { + mtex->tex->id.us--; + MEM_freeN( mtex ); + self->world->mtex[i] = NULL; + } + } + + Py_DECREF(value); + return 0; +} diff --git a/source/blender/python/api2_2x/doc/Texture.py b/source/blender/python/api2_2x/doc/Texture.py index 223c5e6ebdd..b5b82b1a519 100644 --- a/source/blender/python/api2_2x/doc/Texture.py +++ b/source/blender/python/api2_2x/doc/Texture.py @@ -195,20 +195,23 @@ Example:: - DN_CELLNOISE - Steven Worley's cellular basis algorithm (1996) @var TexCo: Flags for MTex.texco. - - ORCO - Use the original coordinates of the mesh - - REFL - Use reflection vector as texture coordinates - - NOR - Use normal vector as texture coordinates + - ORCO - Use the original coordinates of the mesh (material texture only) + - REFL - Use reflection vector as texture coordinates (material texture only) + - NOR - Use normal vector as texture coordinates (material texture only) - GLOB - Use global coordinates for the texture coordinates - - UV - Use UV coordinates for texture coordinates + - UV - Use UV coordinates for texture coordinates (material texture only) - OBJECT - Use linked object's coordinates for texture coordinates - - WIN - Use screen coordinates as texture coordinates - - VIEW - Pass camera view vector on to the texture (World texture only!) - - STICK - Use mesh sticky coordinates for the texture coordinates - - STRESS - Use mesh stress coordinates for the texture coordinates - - TANGENT - Use mesh tangent coordinates for the texture coordinates + - WIN - Use screen coordinates as texture coordinates (material texture only) + - VIEW - Use view coordinates for the texture (world and lamp texture only) + - STICK - Use mesh sticky coordinates for the texture coordinates (material texture only) + - STRESS - Use mesh stress coordinates for the texture coordinates (material texture only) + - TANGENT - Use mesh tangent coordinates for the texture coordinates (material texture only) + - ANGMAP - Uses 360 degree angular coordinates, e.g. for spherical light probes (world texture only) + - HSPHERE - For 360 degree panorama sky, spherical mapped, only top half (world texture only) + - HTUBE - For 360 degree panorama sky, cylindrical mapped, only top half (world texture only) @type TexCo: readonly dictionary -@var MapTo: Flags for MTex.mapto. +@var MapTo: Flags for MTex.mapto - COL - Make the texture affect the basic color of the material - NOR - Make the texture affect the rendered normal - CSP - Make the texture affect the specularity color @@ -500,84 +503,92 @@ class MTex: This object links a material to a texture. It allows the same texture to be used in several different ways. - @type blendmode: int @ivar blendmode: Texture blending mode. See L{BlendModes} + @type blendmode: int + @ivar col: Color that the texture blends with. @type col: tuple - @ivar col: Color that the texture blends with. Range of. - @type colfac: float @ivar colfac: Factor by which texture affects color. - @ivar correctNor: Correct normal mapping for Texture space and Object space. + @type colfac: float + @ivar correctNor: Correct normal mapping for Texture space and Object space (material only). @type correctNor: boolean + @ivar dispfac: Factor by which texture affects displacement (material only). @type dispfac: float - @ivar dispfac: Factor by which texture affects displacement. - @type dvar: float @ivar dvar: Value that the texture blends with when not blending colors. + @type dvar: float + @ivar fromDupli: Duplis instanced from verts, faces or particles, inherit texture coordinate from their parent (material only). @type fromDupli: boolean - @ivar fromDupli: Duplis instanced from verts, faces or particles, inherit texture coordinate from their parent. + @ivar fromOrig: Duplis derive their object coordinates from the original objects transformation (material only). @type fromOrig: boolean - @ivar fromOrig: Duplis derive their object coordinates from the original objects transformation. + @ivar mapping: Mapping of texture coordinates (flat, cube, etc.) (material only). See L{Mappings}. @type mapping: int - @ivar mapping: Mapping of texture coordinates (flat, cube, etc.). See L{Mappings}. + @ivar mapto: "Map to" field of texture (material only). OR'd values of L{MapTo}. @type mapto: int - @ivar mapto: "Map to" field of texture. OR'd values of L{MapTo}. - @ivar mtAlpha: How texture maps to alpha value. - @type mtAlpha: int - @ivar mtAmb: How texture maps to ambient value. - @type mtAmb: int - @ivar mtCmir: How texture maps to mirror color. - @type mtCmir: int - @ivar mtCol: How texture maps to color. + @ivar mtCol: How texture maps to color (material and lamp only). @type mtCol: int - @ivar mtCsp: How texture maps to specularity color + @ivar mtAlpha: How texture maps to alpha value (material only). + @type mtAlpha: int + @ivar mtAmb: How texture maps to ambient value (material only). + @type mtAmb: int + @ivar mtCmir: How texture maps to mirror color (material only). + @type mtCmir: int + @ivar mtCsp: How texture maps to specularity color (material only). @type mtCsp: int - @ivar mtDisp: How texture maps to displacement + @ivar mtDisp: How texture maps to displacement (material only). @type mtDisp: int - @ivar mtEmit: How texture maps to emit value + @ivar mtEmit: How texture maps to emit value (material only). @type mtEmit: int - @ivar mtHard: How texture maps to hardness + @ivar mtHard: How texture maps to hardness (material only). @type mtHard: int - @ivar mtNor: How texture maps to normals + @ivar mtNor: How texture maps to normals (material only). @type mtNor: int - @ivar mtRayMir: How texture maps to RayMir value + @ivar mtRayMir: How texture maps to RayMir value (material only). @type mtRayMir: int - @ivar mtRef: How texture maps to reflectivity + @ivar mtRef: How texture maps to reflectivity (material only). @type mtRef: int - @ivar mtSpec: How texture maps to specularity + @ivar mtSpec: How texture maps to specularity (material only). @type mtSpec: int - @ivar mtTranslu: How texture maps to translucency + @ivar mtTranslu: How texture maps to translucency (material only). @type mtTranslu: int - @ivar mtWarp: How texture maps to warp + @ivar mtWarp: How texture maps to warp (material only). @type mtWarp: int - @ivar neg: Negate texture values mode + @ivar mtBlend: Texture affects color progression of background (world only). + @type mtBlend: int + @ivar mtHoriz: Texture affects color of the horizon (world only). + @type mtHoriz: int + @ivar mtZenUp: Texture affects color of the zenith above (world only). + @type mtZenUp: int + @ivar mtZenDown: Texture affects color of the zenith below (world only). + @type mtZenDown: int + @ivar neg: Negate texture values mode. @type neg: boolean - @ivar norfac: Factor by which texture affects normal + @ivar norfac: Factor by which texture affects normal (material and world only). @type norfac: float - @ivar noRGB: Convert texture RGB values to intensity values + @ivar noRGB: Convert texture RGB values to intensity values. @type noRGB: boolean - @ivar object: Object whose space to use when texco is Object + @ivar object: Object whose space to use when texco is Object. @type object: Blender Object or None + @ivar ofs: Offset to adjust texture space. @type ofs: tuple - @ivar ofs: Offset to adjust texture space + @ivar size: Size to scale texture space. @type size: tuple - @ivar size: Size to scale texture space - @ivar stencil: Stencil mode + @ivar stencil: Stencil mode. @type stencil: boolean @ivar tex: The Texture this is linked to. @type tex: Blender Texture - @ivar texco: Texture coordinates ("Map input"). See L{TexCo} + @ivar texco: Texture coordinates ("Map input"). See L{TexCo}. @type texco: int - @ivar uvlayer: The name of the UV Layer this texture is mapped to (when left blank uses render layer) + @ivar uvlayer: The name of the UV Layer this texture is mapped to (when left blank uses render layer) (material only). @type uvlayer: string + @ivar varfac: Factor by which texture affects most variables (material and world only). @type varfac: float - @ivar varfac: Factor by which texture affects most variables + @ivar warpfac: Factor by which texture affects warp (material only). @type warpfac: float - @ivar warpfac: Factor by which texture affects warp + @ivar xproj: Projection of X axis to Texture space (material only). See L{Proj} @type xproj: int - @ivar xproj: Projection of X axis to Texture space. See L{Proj} + @ivar yproj: Projection of Y axis to Texture space (material only). See L{Proj} @type yproj: int - @ivar yproj: Projection of Y axis to Texture space. See L{Proj} + @ivar zproj: Projection of Z axis to Texture space (material only). See L{Proj} @type zproj: int - @ivar zproj: Projection of Z axis to Texture space. See L{Proj} """ def getIpo(): From d86c4c1004ad4451f4c66f7b6015a16eba031e03 Mon Sep 17 00:00:00 2001 From: Ken Hughes Date: Fri, 12 Sep 2008 05:02:06 +0000 Subject: [PATCH 029/125] Python API ---------- Patch #17481: added Material attributes for missing colorbands controls: * material.colorbandDiffuseInput * material.colorbandDiffuseMethod * material.colorbandDiffuseFactor * material.colorbandSpecularInput * material.colorbandSpecularMethod * material.colorbandSpecularFactor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Contributed by Emilio José Encinas Mir (asfhy). Thanks! --- source/blender/python/api2_2x/Material.c | 164 +++++++++++++++++- source/blender/python/api2_2x/doc/Material.py | 51 ++++++ 2 files changed, 213 insertions(+), 2 deletions(-) diff --git a/source/blender/python/api2_2x/Material.c b/source/blender/python/api2_2x/Material.c index 145629d0aaa..842127650d7 100644 --- a/source/blender/python/api2_2x/Material.c +++ b/source/blender/python/api2_2x/Material.c @@ -155,6 +155,8 @@ #define EXPP_MAT_SPECTRANS_MAX 1.0 #define EXPP_MAT_MIRRTRANSADD_MIN 0.0 #define EXPP_MAT_MIRRTRANSADD_MAX 1.0 +#define EXPP_MAT_COLORBAND_FACTOR_MIN 0.0 +#define EXPP_MAT_COLORBAND_FACTOR_MAX 1.0 /* closure values for getColorComponent()/setColorComponent() */ @@ -403,19 +405,62 @@ static PyObject *Material_ShadersDict( void ) return Shaders; } +static PyObject *Material_ColorRampMethodsDict( void ) +{ + PyObject *Methods = PyConstant_New( ); + if( Methods ) { + BPy_constant *c = (BPy_constant * ) Methods; + + PyConstant_Insert(c, "BLEND", PyInt_FromLong(MA_RAMP_BLEND)); + PyConstant_Insert(c, "MIX", PyInt_FromLong(MA_RAMP_BLEND)); /* This one is added to solve confusion between Blend-Mix name. */ + PyConstant_Insert(c, "ADD", PyInt_FromLong(MA_RAMP_ADD)); + PyConstant_Insert(c, "MULT", PyInt_FromLong(MA_RAMP_MULT)); + PyConstant_Insert(c, "SUB", PyInt_FromLong(MA_RAMP_SUB)); + PyConstant_Insert(c, "SCREEN", PyInt_FromLong(MA_RAMP_SCREEN)); + PyConstant_Insert(c, "DIV", PyInt_FromLong(MA_RAMP_DIV)); + PyConstant_Insert(c, "DIFF", PyInt_FromLong(MA_RAMP_DIFF)); + PyConstant_Insert(c, "DARK", PyInt_FromLong(MA_RAMP_DARK)); + PyConstant_Insert(c, "LIGHT", PyInt_FromLong(MA_RAMP_LIGHT)); + PyConstant_Insert(c, "OVERLAY", PyInt_FromLong(MA_RAMP_OVERLAY)); + PyConstant_Insert(c, "DODGE", PyInt_FromLong(MA_RAMP_DODGE)); + PyConstant_Insert(c, "BURN", PyInt_FromLong(MA_RAMP_BURN)); + PyConstant_Insert(c, "HUE", PyInt_FromLong(MA_RAMP_HUE)); + PyConstant_Insert(c, "SAT", PyInt_FromLong(MA_RAMP_SAT)); + PyConstant_Insert(c, "VAL", PyInt_FromLong(MA_RAMP_VAL)); + PyConstant_Insert(c, "COLOR", PyInt_FromLong(MA_RAMP_COLOR)); + + } + return Methods; +} + +static PyObject *Material_ColorRampInputDict( void ) +{ + PyObject *Inputs = PyConstant_New( ); + if( Inputs ) { + BPy_constant *c = (BPy_constant * ) Inputs; + + PyConstant_Insert(c, "SHADER", PyInt_FromLong(MA_RAMP_IN_SHADER)); + PyConstant_Insert(c, "ENERGY", PyInt_FromLong(MA_RAMP_IN_ENERGY)); + PyConstant_Insert(c, "NORMAL", PyInt_FromLong(MA_RAMP_IN_NOR)); + PyConstant_Insert(c, "RESULT", PyInt_FromLong(MA_RAMP_IN_RESULT)); + } + return Inputs; +} /*****************************************************************************/ /* Function: Material_Init */ /*****************************************************************************/ PyObject *Material_Init( void ) { - PyObject *submodule, *Modes, *Shaders; + PyObject *submodule, *Modes, *Shaders, *ColorbandInput, *ColorbandMethod; if( PyType_Ready( &Material_Type ) < 0) return NULL; Modes = Material_ModesDict( ); Shaders = Material_ShadersDict( ); + ColorbandMethod = Material_ColorRampMethodsDict( ); + ColorbandInput = Material_ColorRampInputDict( ); submodule = Py_InitModule3( "Blender.Material", M_Material_methods, M_Material_doc ); @@ -424,6 +469,10 @@ PyObject *Material_Init( void ) PyModule_AddObject( submodule, "Modes", Modes ); if( Shaders ) PyModule_AddObject( submodule, "Shaders", Shaders ); + if( ColorbandMethod ) + PyModule_AddObject( submodule, "ColorbandMethod", ColorbandMethod ); + if( ColorbandInput ) + PyModule_AddObject( submodule, "ColorbandInput", ColorbandInput ); PyModule_AddIntConstant( submodule, "RGB", IPOKEY_RGB ); PyModule_AddIntConstant( submodule, "ALPHA", IPOKEY_ALPHA ); @@ -652,6 +701,21 @@ int Material_setColorband( BPy_Material * self, PyObject * value, void * type); static PyObject *Material_copy( BPy_Material * self ); static PyObject *Material_freeNodes( BPy_Material * self ); +static PyObject *Material_getColorbandDiffuseFactor( BPy_Material * self ); +static PyObject *Material_getColorbandSpecularFactor( BPy_Material * self ); +static int Material_setColorbandDiffuseFactor ( BPy_Material * self, PyObject * value ); +static int Material_setColorbandSpecularFactor ( BPy_Material * self, PyObject * value ); +static PyObject *Material_getColorbandDiffuseMethod( BPy_Material * self ); +static PyObject *Material_getColorbandSpecularMethod ( BPy_Material * self ); +static int Material_setColorbandDiffuseMethod ( BPy_Material * self, PyObject * value); +static int Material_setColorbandSpecularMethod ( BPy_Material * self, PyObject * value); +static PyObject *Material_getColorbandDiffuseInput( BPy_Material * self ); +static PyObject *Material_getColorbandSpecularInput( BPy_Material * self ); +static int Material_setColorbandDiffuseInput ( BPy_Material * self, PyObject * value); +static int Material_setColorbandSpecularInput ( BPy_Material * self, PyObject * value); + + + /*****************************************************************************/ /* Python BPy_Material methods table: */ /*****************************************************************************/ @@ -1176,7 +1240,31 @@ static PyGetSetDef BPy_Material_getseters[] = { (getter)Material_getTextures, (setter)Material_setTextures, "The Material's texture list as a tuple", NULL}, - + {"colorbandSpecularFactor", + (getter)Material_getColorbandSpecularFactor, (setter)Material_setColorbandSpecularFactor, + "The specular colorband factor for this material", + NULL}, + {"colorbandSpecularMethod", + (getter)Material_getColorbandSpecularMethod, (setter)Material_setColorbandSpecularMethod, + "The specular colorband method for this material", + NULL}, + {"colorbandSpecularInput", + (getter)Material_getColorbandSpecularInput, (setter)Material_setColorbandSpecularInput, + "The specular colorband input for this material", + NULL}, + {"colorbandDiffuseFactor", + (getter)Material_getColorbandDiffuseFactor, (setter)Material_setColorbandDiffuseFactor, + "The diffuse colorband factor for this material", + NULL}, + {"colorbandDiffuseMethod", + (getter)Material_getColorbandDiffuseMethod, (setter)Material_setColorbandDiffuseMethod, + "The diffuse colorband method for this material", + NULL}, + {"colorbandDiffuseInput", + (getter)Material_getColorbandDiffuseInput, (setter)Material_setColorbandDiffuseInput, + "The diffuse colorband input for this material", + NULL}, + /* SSS settings */ {"enableSSS", (getter)Material_getSssEnable, (setter)Material_setSssEnable, @@ -3312,3 +3400,75 @@ static PyObject *Material_clearIpo( BPy_Material * self ) return EXPP_incr_ret_False(); /* no ipo found */ } +/* RampCol Factor */ + +static PyObject *Material_getColorbandDiffuseFactor( BPy_Material * self ) +{ + return PyFloat_FromDouble( (double) self->material->rampfac_col); +} + +static PyObject *Material_getColorbandSpecularFactor( BPy_Material * self ) +{ + return PyFloat_FromDouble( (double) self->material->rampfac_spec); +} + +static int Material_setColorbandDiffuseFactor ( BPy_Material * self, PyObject * value ) +{ + return EXPP_setFloatClamped(value, &self->material->rampfac_col, + EXPP_MAT_COLORBAND_FACTOR_MIN, EXPP_MAT_COLORBAND_FACTOR_MAX); +} + +static int Material_setColorbandSpecularFactor ( BPy_Material * self, PyObject * value ) +{ + return EXPP_setFloatClamped(value, &self->material->rampfac_spec, + EXPP_MAT_COLORBAND_FACTOR_MIN, EXPP_MAT_COLORBAND_FACTOR_MAX); +} + +/* RampCol Method */ + +static PyObject *Material_getColorbandDiffuseMethod( BPy_Material * self ) +{ + return PyInt_FromLong( (long) self->material->rampblend_col); +} + +static PyObject *Material_getColorbandSpecularMethod ( BPy_Material * self ) +{ + return PyInt_FromLong( (long) self->material->rampblend_spec); +} + +static int Material_setColorbandDiffuseMethod ( BPy_Material * self, PyObject * value) +{ + return EXPP_setIValueClamped(value, &self->material->rampblend_col, + MA_RAMP_BLEND, MA_RAMP_COLOR, 'b'); +} + +static int Material_setColorbandSpecularMethod ( BPy_Material * self, PyObject * value) +{ + return EXPP_setIValueClamped(value, &self->material->rampblend_spec, + MA_RAMP_BLEND, MA_RAMP_COLOR, 'b'); +} + +/* RampCol Input */ + +static PyObject *Material_getColorbandDiffuseInput( BPy_Material * self ) +{ + return PyInt_FromLong( (long) self->material->rampin_col); +} + +static PyObject *Material_getColorbandSpecularInput( BPy_Material * self ) +{ + return PyInt_FromLong( (long) self->material->rampin_spec); +} + +static int Material_setColorbandDiffuseInput ( BPy_Material * self, PyObject * value) +{ + return EXPP_setIValueClamped(value, &self->material->rampin_col, + MA_RAMP_IN_SHADER, MA_RAMP_IN_RESULT, 'b'); +} + +static int Material_setColorbandSpecularInput ( BPy_Material * self, PyObject * value) +{ + return EXPP_setIValueClamped(value, &self->material->rampin_spec, + MA_RAMP_IN_SHADER, MA_RAMP_IN_RESULT, 'b'); +} + diff --git a/source/blender/python/api2_2x/doc/Material.py b/source/blender/python/api2_2x/doc/Material.py index 8d45449762c..fa6a9f7047a 100644 --- a/source/blender/python/api2_2x/doc/Material.py +++ b/source/blender/python/api2_2x/doc/Material.py @@ -80,6 +80,35 @@ Example:: - SPEC_BLINN - Make Material use the Blinn specular shader. - SPEC_TOON - Make Material use the toon specular shader. - SPEC_WARDISO - Make Material use the Ward-iso specular shader. + +@type ColorbandMethod: readonly dictionary +@var ColorbandMethod: The available Colorband mixing methods. + - ADD - Make Material use the Add method. + - BLEND - Make Material use the Blend/Mix method. + - BURN - Make Material use the Burn method. + - COLOR - Make Material use the Color method. + - DARK - Make Material use the Darken method. + - DIFF - Make Material use the Difference method. + - DIV - Make Material use the Divide method. + - DODGE - Make Material use the Dodge method. + - HUE - Make Material use the Hue method. + - LIGHT - Make Material use the Lighten method. + - MIX - Make Material use the Blend/Mix method. + - MULT - Make Material use the Multiply method. + - OVERLAY - Make Material use the Overlay method. + - SAT - Make Material use the Saturation method. + - SCREEN - Make Material use the Screen method. + - SUB - Make Material use the Substract method. + - VAL - Make Material use the Value method. + +@type ColorbandInput: readonly dictionary +@var ColorbandInput: The available Colorband Input sources. + - ENERGY - Make Material use the Energy input. + - NORMAL - Make Material use the Normal input. + - RESULT - Make Material use the Result input. + - SHADER - Make Material use the Shader input. + + """ def New (name = 'Mat'): @@ -323,6 +352,28 @@ class Material: each color a list of 5 floats [0 - 1], [r,g,b,a,pos]. The colorband can have between 1 and 31 colors. @type colorbandSpecular: list + @ivar colorbandDiffuseInput: Material Diffuse colorband input. + The integer result must be compared with L{ColorbandInput} + dictionary. + @type colorbandDiffuseInput: int + @ivar colorbandDiffuseMethod: Material Diffuse colorband method. + The integer result must be compared with L{ColorbandMethod} + dictionary. + @type colorbandDiffuseMethod: int + @ivar colorbandDiffuseFactor: Material Diffuse colorband factor. + Value is clamped to the range [0.0,1.0]. + @type colorbandDiffuseFactor: float + @ivar colorbandSpecularInput: Material Specular colorband input. + The integer result must be compared with L{ColorbandInput} + dictionary. + @type colorbandSpecularInput: int + @ivar colorbandSpecularMethod: Material Specular colorband method. + The integer result must be compared with L{ColorbandMethod} + dictionary. + @type colorbandSpecularMethod: int + @ivar colorbandSpecularFactor: Material Specular colorband factor. + Value is clamped to the range [0.0,1.0]. + @type colorbandSpecularFactor: float @type enabledTextures: list of integers @ivar enabledTextures: The texture channels enabled in this material. The attribute returns is list of integers in the range [0, 9], each From c45f1f504b96887b4aea860dffe6705742da6118 Mon Sep 17 00:00:00 2001 From: Diego Borghetti Date: Fri, 12 Sep 2008 05:14:57 +0000 Subject: [PATCH 030/125] Fix segmentation fault in ipo transform. The NLA_IPO_SCALED define don't check if we have a Ipo Space open, so in some case (like when you move a rig with locrot key) when the function make_ipokey_transform is called, Blender crash. --- source/blender/include/BIF_editaction.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/include/BIF_editaction.h b/source/blender/include/BIF_editaction.h index 77c2f19bb9b..1425cf6a67c 100644 --- a/source/blender/include/BIF_editaction.h +++ b/source/blender/include/BIF_editaction.h @@ -78,7 +78,7 @@ enum { #define SEL_GPL(gpl) ((gpl->flag & GP_LAYER_ACTIVE) || (gpl->flag & GP_LAYER_SELECT)) #define NLA_ACTION_SCALED (G.saction->mode==SACTCONT_ACTION && G.saction->pin==0 && OBACT && OBACT->action) -#define NLA_IPO_SCALED (OBACT && OBACT->action && G.sipo->pin==0 && G.sipo->actname) +#define NLA_IPO_SCALED (OBACT && OBACT->action && G.sipo && G.sipo->pin==0 && G.sipo->actname) /* constants for setting ipo-interpolation type */ enum { From 3e5549213c11a582312da0bf5290a6b9b2b7f74c Mon Sep 17 00:00:00 2001 From: Ken Hughes Date: Fri, 12 Sep 2008 05:27:02 +0000 Subject: [PATCH 031/125] Add some typecasts for intptr_t and uintptr_t value to fix gcc warnings. --- source/blender/blenkernel/intern/exotic.c | 14 +++++++------- source/blender/src/sequence.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/intern/exotic.c b/source/blender/blenkernel/intern/exotic.c index fb48c875995..479be2ee644 100644 --- a/source/blender/blenkernel/intern/exotic.c +++ b/source/blender/blenkernel/intern/exotic.c @@ -2632,17 +2632,17 @@ static void write_videoscape_mesh(Object *ob, char *str) if(evl->v4==0) { fprintf(fp, "3 %ld %ld %ld 0x%x\n", - evl->v1->tmp.l, - evl->v2->tmp.l, - evl->v3->tmp.l, + (long int) evl->v1->tmp.l, + (long int) evl->v2->tmp.l, + (long int) evl->v3->tmp.l, kleur[evl->mat_nr]); } else { fprintf(fp, "4 %ld %ld %ld %ld 0x%x\n", - evl->v1->tmp.l, - evl->v2->tmp.l, - evl->v3->tmp.l, - evl->v4->tmp.l, + (long int) evl->v1->tmp.l, + (long int) evl->v2->tmp.l, + (long int) evl->v3->tmp.l, + (long int) evl->v4->tmp.l, kleur[evl->mat_nr]); } evl= evl->next; diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index bf24c02e723..f64a372436c 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -2959,7 +2959,7 @@ void do_render_seq(RenderResult *rr, int cfra) if (max != 0 && mem_in_use + mmap_in_use > max) { fprintf(stderr, "mem_in_use = %lu, max = %lu\n", - mem_in_use + mmap_in_use, max); + (long unsigned int)mem_in_use + mmap_in_use, (long unsigned int)max); fprintf(stderr, "Cleaning up, please wait...\n" "If this happens very often,\n" "consider " From 215828455ac07612e4f2bf47859fc850bda0ef60 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 12 Sep 2008 05:54:39 +0000 Subject: [PATCH 032/125] IPO Editor - Zoom view to area The Shift-B hotkey can now be used to access this tool. --- source/blender/src/header_ipo.c | 2 +- source/blender/src/space.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/src/header_ipo.c b/source/blender/src/header_ipo.c index 59d542e72ec..130ffa1e49f 100644 --- a/source/blender/src/header_ipo.c +++ b/source/blender/src/header_ipo.c @@ -1414,7 +1414,7 @@ void ipo_buttons(void) uiClearButLock(); /* ZOOMBORDER */ - uiDefIconBut(block, BUT, B_IPOBORDER, ICON_BORDERMOVE, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Zooms view to area"); + uiDefIconBut(block, BUT, B_IPOBORDER, ICON_BORDERMOVE, xco+=XIC,0,XIC,YIC, 0, 0, 0, 0, 0, "Zooms view to area (Shift B)"); xco+=XIC/2; diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 749b097a21b..9120fc3de76 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -3103,6 +3103,9 @@ static void winqreadipospace(ScrArea *sa, void *spacedata, BWinEvent *evt) else if (G.qual==LR_CTRLKEY) { borderselect_markers(); } + else if (G.qual==LR_SHIFTKEY) { + do_ipo_buttons(B_IPOBORDER); + } break; case CKEY: if (G.qual == LR_SHIFTKEY) From 1adc2dce52499ca898984dd00a0cd969ff3a6709 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 12 Sep 2008 12:33:55 +0000 Subject: [PATCH 033/125] Correct half of rev16483, which does typecasts which are not nice on Win64 plattform --- source/blender/src/sequence.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/blender/src/sequence.c b/source/blender/src/sequence.c index f64a372436c..5be11a724f1 100644 --- a/source/blender/src/sequence.c +++ b/source/blender/src/sequence.c @@ -2958,8 +2958,7 @@ void do_render_seq(RenderResult *rr, int cfra) max = MEM_CacheLimiter_get_maximum(); if (max != 0 && mem_in_use + mmap_in_use > max) { - fprintf(stderr, "mem_in_use = %lu, max = %lu\n", - (long unsigned int)mem_in_use + mmap_in_use, (long unsigned int)max); + fprintf(stderr, "Memory in use > maximum memory\n"); fprintf(stderr, "Cleaning up, please wait...\n" "If this happens very often,\n" "consider " From 0795d01df4f340bf7435f02d192bef342867af11 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Fri, 12 Sep 2008 13:15:52 +0000 Subject: [PATCH 034/125] Bugfix [#17609] Complex particles crash II - related to #17592 --- source/blender/blenkernel/intern/particle_system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 077af2851a5..ccb5d4829cc 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2678,7 +2678,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P state->vel,force_field,0, pd->rng, pd->f_noise,charge,pa->size); } } - else if(pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){ + else if(pd & pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){ /* first step after key release */ psys_get_particle_state(eob,epsys,p,&estate,1); VECADD(vel,vel,estate.vel); From b0d9994220a0960889e871bd7f3513f075ff2007 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 12 Sep 2008 13:24:22 +0000 Subject: [PATCH 035/125] made max sounds playable at once 32 rather then 16. (demo release background music would turn off otherwise) made selecting sound samples keep the relative path setting. --- intern/SoundSystem/SoundDefines.h | 2 +- source/blender/src/buttons_scene.c | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/intern/SoundSystem/SoundDefines.h b/intern/SoundSystem/SoundDefines.h index 5d425a8dc94..9758fdaadea 100644 --- a/intern/SoundSystem/SoundDefines.h +++ b/intern/SoundSystem/SoundDefines.h @@ -44,7 +44,7 @@ enum /* general stuff */ #define NUM_BUFFERS 128 -#define NUM_SOURCES 16 +#define NUM_SOURCES 32 /* openal related stuff */ #define AL_LOOPING 0x1007 diff --git a/source/blender/src/buttons_scene.c b/source/blender/src/buttons_scene.c index 5205be3e1b0..f2e20356f21 100644 --- a/source/blender/src/buttons_scene.c +++ b/source/blender/src/buttons_scene.c @@ -211,9 +211,15 @@ void do_soundbuts(unsigned short event) case B_SOUND_MENU_SAMPLE: if (G.buts->menunr > 0) { sample = BLI_findlink(samples, G.buts->menunr - 1); - if (sample && sound) { + if (sample && sound && sound->sample != sample) { + int wasrelative = (strncmp(sound->name, "//", 2)==0); + BLI_strncpy(sound->name, sample->name, sizeof(sound->name)); sound_set_sample(sound, sample); + + if (wasrelative) + BLI_makestringcode(G.sce, sound->name); + do_soundbuts(B_SOUND_REDRAW); } } From f40aa6d13f9e50cd695237fd486304ddbff5228d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 12 Sep 2008 13:26:49 +0000 Subject: [PATCH 036/125] typo in recent commit --- source/blender/blenkernel/intern/particle_system.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index ccb5d4829cc..3f5911b896b 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2678,7 +2678,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P state->vel,force_field,0, pd->rng, pd->f_noise,charge,pa->size); } } - else if(pd & pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){ + else if(pd && pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){ /* first step after key release */ psys_get_particle_state(eob,epsys,p,&estate,1); VECADD(vel,vel,estate.vel); From 6ebd6cfa73aa96af2b97384242b716e75897766f Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Fri, 12 Sep 2008 15:26:00 +0000 Subject: [PATCH 037/125] Bugfixes in SDL joystick, apparently it gives NULLs in OSX. --- .../GameLogic/SCA_JoystickSensor.cpp | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 403fbfe6f4c..8ef33240592 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -108,6 +108,9 @@ bool SCA_JoystickSensor::Evaluate(CValue* event) bool result = false; bool reset = m_reset && m_level; + if(js==NULL) + return false; + m_reset = false; switch(m_joymode) { @@ -397,7 +400,9 @@ char SCA_JoystickSensor::GetRealAxis_doc[] = "\tReturns a list of the values for each axis .\n"; PyObject* SCA_JoystickSensor::PyGetRealAxis( PyObject* self) { SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - return Py_BuildValue("[iiii]", joy->GetAxis10(), joy->GetAxis11(), joy->GetAxis20(), joy->GetAxis21()); + if(joy) + return Py_BuildValue("[iiii]", joy->GetAxis10(), joy->GetAxis11(), joy->GetAxis20(), joy->GetAxis21()); + return NULL; } @@ -478,7 +483,9 @@ char SCA_JoystickSensor::NumberOfAxes_doc[] = "\tReturns the number of axes .\n"; PyObject* SCA_JoystickSensor::PyNumberOfAxes( PyObject* self ) { SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - return PyInt_FromLong( joy->GetNumberOfAxes() ); + if(joy) + return PyInt_FromLong( joy->GetNumberOfAxes() ); + return false; } @@ -487,7 +494,9 @@ char SCA_JoystickSensor::NumberOfButtons_doc[] = "\tReturns the number of buttons .\n"; PyObject* SCA_JoystickSensor::PyNumberOfButtons( PyObject* self ) { SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - return PyInt_FromLong( joy->GetNumberOfButtons() ); + if(joy) + return PyInt_FromLong( joy->GetNumberOfButtons() ); + return false; } @@ -496,7 +505,9 @@ char SCA_JoystickSensor::NumberOfHats_doc[] = "\tReturns the number of hats .\n"; PyObject* SCA_JoystickSensor::PyNumberOfHats( PyObject* self ) { SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - return PyInt_FromLong( joy->GetNumberOfHats() ); + if(joy) + return PyInt_FromLong( joy->GetNumberOfHats() ); + return false; } char SCA_JoystickSensor::Connected_doc[] = @@ -504,5 +515,7 @@ char SCA_JoystickSensor::Connected_doc[] = "\tReturns True if a joystick is connected at this joysticks index.\n"; PyObject* SCA_JoystickSensor::PyConnected( PyObject* self ) { SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - return PyBool_FromLong( joy->Connected() ); + if(joy) + return PyBool_FromLong( joy->Connected() ); + return false; } From 21d74deda6a26433ba36e5751ca74f0a162f3279 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 12 Sep 2008 16:06:17 +0000 Subject: [PATCH 038/125] Fixes for game engine runtime on Mac OS X, there were issues working with relative paths. Still doesn't work optimal, since paths are relative to game.blend which is in the app bundle under Contents/Resources, so other files need to be moved there manually at the moment. --- source/blender/gpu/intern/gpu_draw.c | 5 +- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 96 +++++++++++++------ 2 files changed, 72 insertions(+), 29 deletions(-) diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 8922846f365..fe47fa3c60e 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -720,8 +720,9 @@ void GPU_free_images(void) { Image* ima; - for(ima=G.main->image.first; ima; ima=ima->id.next) - GPU_free_image(ima); + if(G.main) + for(ima=G.main->image.first; ima; ima=ima->id.next) + GPU_free_image(ima); } /* OpenGL Materials */ diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 3a9e59c3c25..0b4fde61e1c 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -198,7 +198,53 @@ void usage(char* program) printf("example: %s -g show_framerate = 0 c:\\loadtest.blend\n", program); } -char *get_filename(int argc, char **argv) { +static void make_absolute_filename(char *blendfilename) +{ + int abs = 0; + int filelen; + char cwd[FILE_MAXDIR + FILE_MAXFILE]; + char filename[FILE_MAXDIR + FILE_MAXFILE]; + + cwd[0] = filename[0] = '\0'; + + BLI_strncpy(filename, blendfilename, sizeof(filename)); + filelen = strlen(filename); + + /* relative path checks, could do more tests here... */ +#ifdef WIN32 + /* Account for X:/ and X:\ - should be enough */ + if (filelen >= 3 && filename[1] == ':' && (filename[2] == '\\' || filename[2] == '/')) + abs = 1; +#else + if (filelen >= 2 && filename[0] == '/') + abs = 1 ; +#endif + if (!abs) { + BLI_getwdN(cwd); /* incase the full path to the blend isnt used */ + + if (cwd[0] == '\0') { + printf( + "Could not get the current working directory - $PWD for an unknown reason.\n\t" + "Relative linked files will not load if the entire blend path is not used.\n\t" + "The 'Play' button may also fail.\n" + ); + } else { + /* uses the blend path relative to cwd important for loading relative linked files. + * + * cwd should contain c:\ etc on win32 so the relbase can be NULL + * relbase being NULL also prevents // being misunderstood as relative to the current + * blend file which isnt a feature we want to use in this case since were dealing + * with a path from the command line, rather then from inside Blender */ + + BLI_make_file_string(NULL, filename, cwd, blendfilename); + } + } + + BLI_strncpy(blendfilename, filename, sizeof(filename)); +} + +static void get_filename(int argc, char **argv, char *filename) +{ #ifdef __APPLE__ /* On Mac we park the game file (called game.blend) in the application bundle. * The executable is located in the bundle as well. @@ -206,22 +252,18 @@ char *get_filename(int argc, char **argv) { */ int srclen = ::strlen(argv[0]); int len = 0; - char *filename = NULL; + char *gamefile = NULL; + filename[0] = '\0'; + if (argc > 1) { if (BLI_exists(argv[argc-1])) { - len = ::strlen(argv[argc-1]); - filename = new char [len + 1]; - ::strcpy(filename, argv[argc-1]); - return(filename); + BLI_strncpy(filename, argv[argc-1], FILE_MAXDIR + FILE_MAXFILE); } if (::strncmp(argv[argc-1], "-psn_", 5)==0) { static char firstfilebuf[512]; if (GHOST_HACK_getFirstFile(firstfilebuf)) { - len = ::strlen(firstfilebuf); - filename = new char [len + 1]; - ::strcpy(filename, firstfilebuf); - return(filename); + BLI_strncpy(filename, firstfilebuf, FILE_MAXDIR + FILE_MAXFILE); } } } @@ -229,23 +271,26 @@ char *get_filename(int argc, char **argv) { srclen -= ::strlen("MacOS/blenderplayer"); if (srclen > 0) { len = srclen + ::strlen("Resources/game.blend"); - filename = new char [len + 1]; - ::strcpy(filename, argv[0]); - ::strcpy(filename + srclen, "Resources/game.blend"); + gamefile = new char [len + 1]; + ::strcpy(gamefile, argv[0]); + ::strcpy(gamefile + srclen, "Resources/game.blend"); //::printf("looking for file: %s\n", filename); - if (BLI_exists(filename)) { - return (filename); - } + if (BLI_exists(gamefile)) + BLI_strncpy(filename, gamefile, FILE_MAXDIR + FILE_MAXFILE); + + delete gamefile; } - return(NULL); #else - return (argc>1)?argv[argc-1]:NULL; + filename[0] = '\0'; + + if(argc > 1) + BLI_strncpy(filename, argv[argc-1], FILE_MAXDIR + FILE_MAXFILE); #endif // !_APPLE } -static BlendFileData *load_game_data(char *progname, char *filename = NULL) { +static BlendFileData *load_game_data(char *progname, char *filename = NULL, char *relativename = NULL) { BlendReadError error; BlendFileData *bfd = NULL; @@ -579,9 +624,12 @@ int main(int argc, char** argv) STR_String exitstring = ""; GPG_Application app(system); bool firstTimeRunning = true; - char *filename = get_filename(argc, argv); + char filename[FILE_MAXDIR + FILE_MAXFILE]; char *titlename; char pathname[160]; + + get_filename(argc, argv, filename); + make_absolute_filename(filename); do { @@ -613,7 +661,7 @@ int main(int argc, char** argv) } else { - bfd = load_game_data(bprogname, filename); + bfd = load_game_data(bprogname, filename[0]? filename: NULL); } //::printf("game data loaded from %s\n", filename); @@ -782,12 +830,6 @@ int main(int argc, char** argv) pyGlobalDictString_Length = app.GetPyGlobalDictMarshalLength(); BLO_blendfiledata_free(bfd); - -#ifdef __APPLE__ - if (filename) { - delete [] filename; - } -#endif // __APPLE__ } } while (exitcode == KX_EXIT_REQUEST_RESTART_GAME || exitcode == KX_EXIT_REQUEST_START_OTHER_GAME); } From 206cfe7955683ac166201e417977e933fd98f7b3 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Sat, 13 Sep 2008 05:24:52 +0000 Subject: [PATCH 039/125] avoid crash when game engine returns to Blender, and OpenAL sources haven't been initialized properly for some reason. --- intern/SoundSystem/openal/SND_OpenALDevice.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/intern/SoundSystem/openal/SND_OpenALDevice.cpp b/intern/SoundSystem/openal/SND_OpenALDevice.cpp index 82ed1c8a808..c660e9aecba 100644 --- a/intern/SoundSystem/openal/SND_OpenALDevice.cpp +++ b/intern/SoundSystem/openal/SND_OpenALDevice.cpp @@ -294,6 +294,10 @@ SND_OpenALDevice::SND_OpenALDevice() // let openal generate its sources if (alc_error == ALC_NO_ERROR) { + int i; + + for (i=0;i Date: Sat, 13 Sep 2008 07:06:43 +0000 Subject: [PATCH 040/125] Upgrade to latest Bullet trunk, that is in sync with Blender/extern/bullet2. (except for one define 'WIN32_AVOID_SSE_WHEN_EMBEDDED_INSIDE_BLENDER') In case someone reads those SVN logs: you can enable some extra broadphase SSE optimizations by replacing WIN32_AVOID_SSE_WHEN_EMBEDDED_INSIDE_BLENDER by WIN32 in extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h Thanks to Benoit Bolsee for the upstream patch/contribution. Removed some obsolete files, they were just intended for comparison/testing. --- .../BroadphaseCollision/btAxisSweep3.h | 85 +- .../BroadphaseCollision/btDbvt.cpp | 91 +- .../BroadphaseCollision/btDbvt.h | 198 ++-- .../btSimpleBroadphase.cpp | 66 +- .../BroadphaseCollision/btSimpleBroadphase.h | 21 +- .../src/BulletCollision/CMakeLists.txt | 93 ++ .../CollisionDispatch/btBoxBoxDetector.cpp | 4 +- .../CollisionDispatch/btCollisionObject.cpp | 2 +- .../CollisionDispatch/btCollisionObject.h | 18 +- .../CollisionDispatch/btCollisionWorld.cpp | 13 +- .../btCompoundCollisionAlgorithm.cpp | 211 ++++- .../btCompoundCollisionAlgorithm.h | 7 +- .../btDefaultCollisionConfiguration.cpp | 12 +- .../btDefaultCollisionConfiguration.h | 3 + .../btSphereTriangleCollisionAlgorithm.cpp | 2 +- .../CollisionShapes/btBoxShape.cpp | 14 +- .../CollisionShapes/btCapsuleShape.h | 3 +- .../CollisionShapes/btCompoundShape.cpp | 190 ++-- .../CollisionShapes/btCompoundShape.h | 42 +- .../btConvexTriangleMeshShape.cpp | 110 +++ .../btConvexTriangleMeshShape.h | 7 + .../btHeightfieldTerrainShape.cpp | 8 +- .../CollisionShapes/btOptimizedBvh.cpp | 2 + .../CollisionShapes/btPolyhedralConvexShape.h | 24 +- .../btScaledBvhTriangleMeshShape.cpp | 103 ++ .../btScaledBvhTriangleMeshShape.h | 57 ++ .../CollisionShapes/btTriangleMeshShape.cpp | 5 +- .../CollisionShapes/btTriangleMeshShape.h | 10 + .../bullet2/src/BulletDynamics/CMakeLists.txt | 20 +- .../btConeTwistConstraint.cpp | 21 +- .../ConstraintSolver/btHingeConstraint.cpp | 9 +- .../ConstraintSolver/btOdeContactJoint.cpp | 278 ------ .../ConstraintSolver/btOdeContactJoint.h | 50 - .../ConstraintSolver/btOdeJoint.cpp | 25 - .../ConstraintSolver/btOdeJoint.h | 94 -- .../ConstraintSolver/btOdeMacros.h | 212 ----- .../btOdeQuickstepConstraintSolver.cpp | 393 -------- .../btOdeQuickstepConstraintSolver.h | 109 --- .../ConstraintSolver/btOdeSolverBody.h | 48 - .../ConstraintSolver/btOdeTypedJoint.cpp | 880 ------------------ .../ConstraintSolver/btOdeTypedJoint.h | 142 --- .../ConstraintSolver/btSliderConstraint.cpp | 1 + .../ConstraintSolver/btSliderConstraint.h | 3 + .../ConstraintSolver/btSorLcp.cpp | 683 -------------- .../ConstraintSolver/btSorLcp.h | 112 --- .../Dynamics/btDiscreteDynamicsWorld.cpp | 98 +- .../Dynamics/btDiscreteDynamicsWorld.h | 2 +- .../BulletDynamics/Dynamics/btDynamicsWorld.h | 2 +- .../bullet2/src/BulletSoftBody/btSoftBody.cpp | 4 +- .../src/BulletSoftBody/btSoftBodyHelpers.cpp | 3 - .../src/BulletSoftBody/btSoftBodyInternals.h | 3 +- extern/bullet2/src/LinearMath/CMakeLists.txt | 29 +- extern/bullet2/src/LinearMath/btAabbUtil2.h | 34 + extern/bullet2/src/LinearMath/btMatrix3x3.h | 85 ++ extern/bullet2/src/LinearMath/btScalar.h | 25 +- extern/bullet2/src/btBulletCollisionCommon.h | 4 +- extern/bullet2/src/btBulletDynamicsCommon.h | 4 +- 57 files changed, 1303 insertions(+), 3471 deletions(-) create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp create mode 100644 extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeContactJoint.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeContactJoint.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeJoint.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeJoint.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeMacros.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeQuickstepConstraintSolver.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeQuickstepConstraintSolver.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeSolverBody.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeTypedJoint.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeTypedJoint.h delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSorLcp.cpp delete mode 100644 extern/bullet2/src/BulletDynamics/ConstraintSolver/btSorLcp.h diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h index e7c5fb5b6cf..d0ad09a385a 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btAxisSweep3.h @@ -27,6 +27,7 @@ #include "btOverlappingPairCallback.h" //#define DEBUG_BROADPHASE 1 +#define USE_OVERLAP_TEST_ON_REMOVES 1 /// The internal templace class btAxisSweep3Internal implements the sweep and prune broadphase. /// It uses quantized integers to represent the begin and end points for each of the 3 axis. @@ -52,9 +53,7 @@ public: }; public: - //This breaks the Intel compiler, see http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/30253577.aspx - class Handle : public btBroadphaseProxy - //ATTRIBUTE_ALIGNED16(class) Handle : public btBroadphaseProxy + class Handle : public btBroadphaseProxy { public: BT_DECLARE_ALIGNED_ALLOCATOR(); @@ -80,7 +79,7 @@ protected: BP_FP_INT_TYPE m_numHandles; // number of active handles BP_FP_INT_TYPE m_maxHandles; // max number of handles Handle* m_pHandles; // handles pool - void* m_pHandlesRawPtr; + BP_FP_INT_TYPE m_firstFreeHandle; // free handles list Edge* m_pEdges[3]; // edge arrays for the 3 axes (each array has m_maxHandles * 2 + 2 sentinel entries) @@ -100,7 +99,7 @@ protected: void freeHandle(BP_FP_INT_TYPE handle); - bool testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB); + bool testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1); #ifdef DEBUG_BROADPHASE void debugPrintAxis(int axis,bool checkCardinality=true); @@ -273,10 +272,9 @@ m_invalidPair(0) m_quantize = btVector3(btScalar(maxInt),btScalar(maxInt),btScalar(maxInt)) / aabbSize; - // allocate handles buffer and put all handles on free list - m_pHandlesRawPtr = btAlignedAlloc(sizeof(Handle)*maxHandles,16); - m_pHandles = new(m_pHandlesRawPtr) Handle[maxHandles]; - + // allocate handles buffer, using btAlignedAlloc, and put all handles on free list + m_pHandles = new Handle[maxHandles]; + m_maxHandles = maxHandles; m_numHandles = 0; @@ -327,7 +325,7 @@ btAxisSweep3Internal::~btAxisSweep3Internal() { btAlignedFree(m_pEdgesRawPtr[i]); } - btAlignedFree(m_pHandlesRawPtr); + delete [] m_pHandles; if (m_ownsPairCache) { @@ -603,34 +601,17 @@ bool btAxisSweep3Internal::testAabbOverlap(btBroadphaseProxy* pr } template -bool btAxisSweep3Internal::testOverlap(int ignoreAxis,const Handle* pHandleA, const Handle* pHandleB) +bool btAxisSweep3Internal::testOverlap2D(const Handle* pHandleA, const Handle* pHandleB,int axis0,int axis1) { //optimization 1: check the array index (memory address), instead of the m_pos - for (int axis = 0; axis < 3; axis++) + if (pHandleA->m_maxEdges[axis0] < pHandleB->m_minEdges[axis0] || + pHandleB->m_maxEdges[axis0] < pHandleA->m_minEdges[axis0] || + pHandleA->m_maxEdges[axis1] < pHandleB->m_minEdges[axis1] || + pHandleB->m_maxEdges[axis1] < pHandleA->m_minEdges[axis1]) { - if (axis != ignoreAxis) - { - if (pHandleA->m_maxEdges[axis] < pHandleB->m_minEdges[axis] || - pHandleB->m_maxEdges[axis] < pHandleA->m_minEdges[axis]) - { - return false; - } - } + return false; } - - //optimization 2: only 2 axis need to be tested (conflicts with 'delayed removal' optimization) - - /*for (int axis = 0; axis < 3; axis++) - { - if (m_pEdges[axis][pHandleA->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleB->m_minEdges[axis]].m_pos || - m_pEdges[axis][pHandleB->m_maxEdges[axis]].m_pos < m_pEdges[axis][pHandleA->m_minEdges[axis]].m_pos) - { - return false; - } - } - */ - return true; } @@ -700,7 +681,9 @@ void btAxisSweep3Internal::sortMinDown(int axis, BP_FP_INT_TYPE if (pPrev->IsMax()) { // if previous edge is a maximum check the bounds and add an overlap if necessary - if (updateOverlaps && testOverlap(axis,pHandleEdge, pHandlePrev)) + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + if (updateOverlaps && testOverlap2D(pHandleEdge, pHandlePrev,axis1,axis2)) { m_pairCache->addOverlappingPair(pHandleEdge,pHandlePrev); if (m_userPairCallback) @@ -748,12 +731,19 @@ void btAxisSweep3Internal::sortMinUp(int axis, BP_FP_INT_TYPE ed if (pNext->IsMax()) { - + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pNext->m_handle); + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + // if next edge is maximum remove any overlap between the two handles - if (updateOverlaps) + if (updateOverlaps +#ifdef USE_OVERLAP_TEST_ON_REMOVES + && testOverlap2D(handle0,handle1,axis1,axis2) +#endif //USE_OVERLAP_TEST_ON_REMOVES + ) { - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pNext->m_handle); + m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); if (m_userPairCallback) @@ -799,12 +789,20 @@ void btAxisSweep3Internal::sortMaxDown(int axis, BP_FP_INT_TYPE if (!pPrev->IsMax()) { // if previous edge was a minimum remove any overlap between the two handles - if (updateOverlaps) + Handle* handle0 = getHandle(pEdge->m_handle); + Handle* handle1 = getHandle(pPrev->m_handle); + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + + if (updateOverlaps +#ifdef USE_OVERLAP_TEST_ON_REMOVES + && testOverlap2D(handle0,handle1,axis1,axis2) +#endif //USE_OVERLAP_TEST_ON_REMOVES + ) { //this is done during the overlappingpairarray iteration/narrowphase collision - Handle* handle0 = getHandle(pEdge->m_handle); - Handle* handle1 = getHandle(pPrev->m_handle); + m_pairCache->removeOverlappingPair(handle0,handle1,dispatcher); if (m_userPairCallback) m_userPairCallback->removeOverlappingPair(handle0,handle1,dispatcher); @@ -850,10 +848,13 @@ void btAxisSweep3Internal::sortMaxUp(int axis, BP_FP_INT_TYPE ed { Handle* pHandleNext = getHandle(pNext->m_handle); + const int axis1 = (1 << axis) & 3; + const int axis2 = (1 << axis1) & 3; + if (!pNext->IsMax()) { // if next edge is a minimum check the bounds and add an overlap if necessary - if (updateOverlaps && testOverlap(axis, pHandleEdge, pHandleNext)) + if (updateOverlaps && testOverlap2D(pHandleEdge, pHandleNext,axis1,axis2)) { Handle* handle0 = getHandle(pEdge->m_handle); Handle* handle1 = getHandle(pNext->m_handle); diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp index fade71179e6..7c41c8d8f71 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.cpp @@ -663,24 +663,23 @@ Benchmarking dbvt... Leaves: 8192 sizeof(btDbvtVolume): 32 bytes sizeof(btDbvtNode): 44 bytes -[1] btDbvtVolume intersections: 3537 ms (0%) -[2] btDbvtVolume merges: 1945 ms (0%) -[3] btDbvt::collideTT: 6646 ms (0%) -[4] btDbvt::collideTT self: 3389 ms (0%) -[5] btDbvt::collideTT xform: 7505 ms (0%) -[6] btDbvt::collideTT xform,self: 7480 ms (0%) -[7] btDbvt::collideRAY: 6307 ms (0%),(332511 r/s) -[8] insert/remove: 2105 ms (-3%),(996271 ir/s) -[9] updates (teleport): 1943 ms (0%),(1079337 u/s) -[10] updates (jitter): 1301 ms (0%),(1611953 u/s) -[11] optimize (incremental): 2510 ms (0%),(1671000 o/s) -[12] btDbvtVolume notequal: 3677 ms (0%) -[13] culling(OCL+fullsort): 2231 ms (0%),(458 t/s) -[14] culling(OCL+qsort): 3500 ms (0%),(2340 t/s) -[15] culling(KDOP+qsort): 1151 ms (0%),(7117 t/s) -[16] insert/remove batch(256): 5138 ms (0%),(816330 bir/s) -[17] btDbvtVolume proximity: 2842 ms (0%) -[18] btDbvtVolume select: 3390 ms (0%) +[1] btDbvtVolume intersections: 3499 ms (-1%) +[2] btDbvtVolume merges: 1934 ms (0%) +[3] btDbvt::collideTT: 5485 ms (-21%) +[4] btDbvt::collideTT self: 2814 ms (-20%) +[5] btDbvt::collideTT xform: 7379 ms (-1%) +[6] btDbvt::collideTT xform,self: 7270 ms (-2%) +[7] btDbvt::collideRAY: 6314 ms (0%),(332143 r/s) +[8] insert/remove: 2093 ms (0%),(1001983 ir/s) +[9] updates (teleport): 1879 ms (-3%),(1116100 u/s) +[10] updates (jitter): 1244 ms (-4%),(1685813 u/s) +[11] optimize (incremental): 2514 ms (0%),(1668000 o/s) +[12] btDbvtVolume notequal: 3659 ms (0%) +[13] culling(OCL+fullsort): 2218 ms (0%),(461 t/s) +[14] culling(OCL+qsort): 3688 ms (5%),(2221 t/s) +[15] culling(KDOP+qsort): 1139 ms (-1%),(7192 t/s) +[16] insert/remove batch(256): 5092 ms (0%),(823704 bir/s) +[17] btDbvtVolume select: 3419 ms (0%) */ struct btDbvtBenchmark @@ -787,7 +786,7 @@ static const bool cfgEnable = true; //[1] btDbvtVolume intersections bool cfgBenchmark1_Enable = cfgEnable; static const int cfgBenchmark1_Iterations = 8; -static const int cfgBenchmark1_Reference = 3537; +static const int cfgBenchmark1_Reference = 3499; //[2] btDbvtVolume merges bool cfgBenchmark2_Enable = cfgEnable; static const int cfgBenchmark2_Iterations = 4; @@ -795,21 +794,21 @@ static const int cfgBenchmark2_Reference = 1945; //[3] btDbvt::collideTT bool cfgBenchmark3_Enable = cfgEnable; static const int cfgBenchmark3_Iterations = 512; -static const int cfgBenchmark3_Reference = 6646; +static const int cfgBenchmark3_Reference = 5485; //[4] btDbvt::collideTT self bool cfgBenchmark4_Enable = cfgEnable; static const int cfgBenchmark4_Iterations = 512; -static const int cfgBenchmark4_Reference = 3389; +static const int cfgBenchmark4_Reference = 2814; //[5] btDbvt::collideTT xform bool cfgBenchmark5_Enable = cfgEnable; static const int cfgBenchmark5_Iterations = 512; static const btScalar cfgBenchmark5_OffsetScale = 2; -static const int cfgBenchmark5_Reference = 7505; +static const int cfgBenchmark5_Reference = 7379; //[6] btDbvt::collideTT xform,self bool cfgBenchmark6_Enable = cfgEnable; static const int cfgBenchmark6_Iterations = 512; static const btScalar cfgBenchmark6_OffsetScale = 2; -static const int cfgBenchmark6_Reference = 7480; +static const int cfgBenchmark6_Reference = 7270; //[7] btDbvt::collideRAY bool cfgBenchmark7_Enable = cfgEnable; static const int cfgBenchmark7_Passes = 32; @@ -824,13 +823,13 @@ static const int cfgBenchmark8_Reference = 2105; bool cfgBenchmark9_Enable = cfgEnable; static const int cfgBenchmark9_Passes = 32; static const int cfgBenchmark9_Iterations = 65536; -static const int cfgBenchmark9_Reference = 1943; +static const int cfgBenchmark9_Reference = 1879; //[10] updates (jitter) bool cfgBenchmark10_Enable = cfgEnable; static const btScalar cfgBenchmark10_Scale = cfgVolumeCenterScale/10000; static const int cfgBenchmark10_Passes = 32; static const int cfgBenchmark10_Iterations = 65536; -static const int cfgBenchmark10_Reference = 1301; +static const int cfgBenchmark10_Reference = 1244; //[11] optimize (incremental) bool cfgBenchmark11_Enable = cfgEnable; static const int cfgBenchmark11_Passes = 64; @@ -857,14 +856,10 @@ bool cfgBenchmark16_Enable = cfgEnable; static const int cfgBenchmark16_BatchCount = 256; static const int cfgBenchmark16_Passes = 16384; static const int cfgBenchmark16_Reference = 5138; -//[17] proximity +//[17] select bool cfgBenchmark17_Enable = cfgEnable; -static const int cfgBenchmark17_Iterations = 8; -static const int cfgBenchmark17_Reference = 2842; -//[18] select -bool cfgBenchmark18_Enable = cfgEnable; -static const int cfgBenchmark18_Iterations = 4; -static const int cfgBenchmark18_Reference = 3390; +static const int cfgBenchmark17_Iterations = 4; +static const int cfgBenchmark17_Reference = 3390; btClock wallclock; printf("Benchmarking dbvt...\r\n"); @@ -1259,32 +1254,6 @@ if(cfgBenchmark17_Enable) {// Benchmark 17 srand(380843); btAlignedObjectArray volumes; - btAlignedObjectArray results; - volumes.resize(cfgLeaves); - results.resize(cfgLeaves); - for(int i=0;i volumes; btAlignedObjectArray results; btAlignedObjectArray indices; volumes.resize(cfgLeaves); @@ -1299,9 +1268,9 @@ if(cfgBenchmark18_Enable) { btSwap(indices[i],indices[rand()%cfgLeaves]); } - printf("[18] btDbvtVolume select: "); + printf("[17] btDbvtVolume select: "); wallclock.reset(); - for(int i=0;i= 1400) #define DBVT_USE_TEMPLATE 1 #else @@ -41,6 +41,9 @@ subject to the following restrictions: #define DBVT_USE_TEMPLATE 0 #endif +// Use only intrinsics instead of inline asm +#define DBVT_USE_INTRINSIC_SSE 1 + // Using memmov for collideOCL #define DBVT_USE_MEMMOVE 1 @@ -57,14 +60,21 @@ subject to the following restrictions: #endif // Specific methods implementation -#ifdef WIN32_AVOID_WHEN_EMBEDDED_INSIDE_BLENDER -#define DBVT_PROXIMITY_IMPL DBVT_IMPL_SSE + +#ifdef WIN32_AVOID_SSE_WHEN_EMBEDDED_INSIDE_BLENDER //there is always some weird compiler that breaks SSE builds #define DBVT_SELECT_IMPL DBVT_IMPL_SSE #define DBVT_MERGE_IMPL DBVT_IMPL_SSE +#define DBVT_INT0_IMPL DBVT_IMPL_SSE #else -#define DBVT_PROXIMITY_IMPL DBVT_IMPL_GENERIC #define DBVT_SELECT_IMPL DBVT_IMPL_GENERIC #define DBVT_MERGE_IMPL DBVT_IMPL_GENERIC +#define DBVT_INT0_IMPL DBVT_IMPL_GENERIC +#endif + +#if (DBVT_SELECT_IMPL==DBVT_IMPL_SSE)|| \ + (DBVT_MERGE_IMPL==DBVT_IMPL_SSE)|| \ + (DBVT_INT0_IMPL==DBVT_IMPL_SSE) +#include #endif // @@ -104,10 +114,6 @@ subject to the following restrictions: #error "DBVT_ENABLE_BENCHMARK undefined" #endif -#ifndef DBVT_PROXIMITY_IMPL -#error "DBVT_PROXIMITY_IMPL undefined" -#endif - #ifndef DBVT_SELECT_IMPL #error "DBVT_SELECT_IMPL undefined" #endif @@ -116,6 +122,10 @@ subject to the following restrictions: #error "DBVT_MERGE_IMPL undefined" #endif +#ifndef DBVT_INT0_IMPL +#error "DBVT_INT0_IMPL undefined" +#endif + // // Defaults volumes // @@ -133,8 +143,8 @@ static inline btDbvtAabbMm FromCR(const btVector3& c,btScalar r); static inline btDbvtAabbMm FromMM(const btVector3& mi,const btVector3& mx); static inline btDbvtAabbMm FromPoints(const btVector3* pts,int n); static inline btDbvtAabbMm FromPoints(const btVector3** ppts,int n); -DBVT_INLINE void Expand(const btVector3 e); -DBVT_INLINE void SignedExpand(const btVector3 e); +DBVT_INLINE void Expand(const btVector3& e); +DBVT_INLINE void SignedExpand(const btVector3& e); DBVT_INLINE bool Contain(const btDbvtAabbMm& a) const; DBVT_INLINE int Classify(const btVector3& n,btScalar o,int s) const; DBVT_INLINE btScalar ProjectMinimum(const btVector3& v,unsigned signs) const; @@ -173,12 +183,12 @@ struct btDbvtNode { btDbvtVolume volume; btDbvtNode* parent; - bool isleaf() const { return(childs[1]==0); } - bool isinternal() const { return(!isleaf()); } + DBVT_INLINE bool isleaf() const { return(childs[1]==0); } + DBVT_INLINE bool isinternal() const { return(!isleaf()); } union { - btDbvtNode* childs[2]; - void* data; - }; + btDbvtNode* childs[2]; + void* data; + }; }; ///The btDbvt class implements a fast dynamic bounding volume tree based on axis aligned bounding boxes (aabb tree). @@ -186,8 +196,6 @@ struct btDbvtNode ///Unlike the btQuantizedBvh, nodes can be dynamically moved around, which allows for change in topology of the underlying data structure. struct btDbvt { - - /* Stack element */ struct sStkNN { @@ -250,8 +258,8 @@ struct btDbvt }; // Fields - btDbvtNode* m_root; - btDbvtNode* m_free; + btDbvtNode* m_root; + btDbvtNode* m_free; int m_lkhd; int m_leaves; unsigned m_opath; @@ -408,17 +416,17 @@ return(box); } // -DBVT_INLINE void btDbvtAabbMm::Expand(const btVector3 e) +DBVT_INLINE void btDbvtAabbMm::Expand(const btVector3& e) { mi-=e;mx+=e; } // -DBVT_INLINE void btDbvtAabbMm::SignedExpand(const btVector3 e) +DBVT_INLINE void btDbvtAabbMm::SignedExpand(const btVector3& e) { -if(e.x()>0) mx.setX(mx.x()+e.x()); else mi.setX(mi.x()+e.x()); -if(e.y()>0) mx.setY(mx.y()+e.y()); else mi.setY(mi.y()+e.y()); -if(e.z()>0) mx.setZ(mx.z()+e.z()); else mi.setZ(mi.z()+e.z()); +if(e.x()>0) mx.setX(mx.x()+e[0]); else mi.setX(mi.x()+e[0]); +if(e.y()>0) mx.setY(mx.y()+e[1]); else mi.setY(mi.y()+e[1]); +if(e.z()>0) mx.setZ(mx.z()+e[2]); else mi.setZ(mi.z()+e[2]); } // @@ -486,12 +494,19 @@ for(int i=0;i<3;++i) DBVT_INLINE bool Intersect( const btDbvtAabbMm& a, const btDbvtAabbMm& b) { +#if DBVT_INT0_IMPL == DBVT_IMPL_SSE +const __m128 rt(_mm_or_ps( _mm_cmplt_ps(_mm_load_ps(b.mx),_mm_load_ps(a.mi)), + _mm_cmplt_ps(_mm_load_ps(a.mx),_mm_load_ps(b.mi)))); +const __int32* pu((const __int32*)&rt); +return((pu[0]|pu[1]|pu[2])==0); +#else return( (a.mi.x()<=b.mx.x())&& (a.mx.x()>=b.mi.x())&& (a.mi.y()<=b.mx.y())&& (a.mx.y()>=b.mi.y())&& (a.mi.z()<=b.mx.z())&& (a.mx.z()>=b.mi.z())); +#endif } // @@ -558,32 +573,8 @@ return(txmax>0); DBVT_INLINE btScalar Proximity( const btDbvtAabbMm& a, const btDbvtAabbMm& b) { -#if DBVT_PROXIMITY_IMPL == DBVT_IMPL_SSE -DBVT_ALIGN btScalar r[1]; -static DBVT_ALIGN const unsigned __int32 mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff}; -__asm - { - mov eax,a - mov ecx,b - movaps xmm0,[eax] - movaps xmm2,[ecx] - movaps xmm1,[eax+16] - movaps xmm3,[ecx+16] - addps xmm0,xmm1 - addps xmm2,xmm3 - subps xmm0,xmm2 - andps xmm0,mask - movhlps xmm1,xmm0 - addps xmm0,xmm1 - pshufd xmm1,xmm0,1 - addss xmm0,xmm1 - movss r,xmm0 - } -return(r[0]); -#else const btVector3 d=(a.mi+a.mx)-(b.mi+b.mx); return(btFabs(d.x())+btFabs(d.y())+btFabs(d.z())); -#endif } // @@ -592,36 +583,57 @@ DBVT_INLINE int Select( const btDbvtAabbMm& o, const btDbvtAabbMm& b) { #if DBVT_SELECT_IMPL == DBVT_IMPL_SSE -DBVT_ALIGN __int32 r[1]; static DBVT_ALIGN const unsigned __int32 mask[]={0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff}; -__asm - { - mov eax,o - mov ecx,a - mov edx,b - movaps xmm0,[eax] - movaps xmm5,mask - addps xmm0,[eax+16] - movaps xmm1,[ecx] - movaps xmm2,[edx] - addps xmm1,[ecx+16] - addps xmm2,[edx+16] - subps xmm1,xmm0 - subps xmm2,xmm0 - andps xmm1,xmm5 - andps xmm2,xmm5 - movhlps xmm3,xmm1 - movhlps xmm4,xmm2 - addps xmm1,xmm3 - addps xmm2,xmm4 - pshufd xmm3,xmm1,1 - pshufd xmm4,xmm2,1 - addss xmm1,xmm3 - addss xmm2,xmm4 - cmpless xmm2,xmm1 - movss r,xmm2 - } -return(r[0]&1); + // TODO: the intrinsic version is 11% slower + #if DBVT_USE_INTRINSIC_SSE + __m128 omi(_mm_load_ps(o.mi)); + omi=_mm_add_ps(omi,_mm_load_ps(o.mx)); + __m128 ami(_mm_load_ps(a.mi)); + ami=_mm_add_ps(ami,_mm_load_ps(a.mx)); + ami=_mm_sub_ps(ami,omi); + ami=_mm_and_ps(ami,_mm_load_ps((const float*)mask)); + __m128 bmi(_mm_load_ps(b.mi)); + bmi=_mm_add_ps(bmi,_mm_load_ps(b.mx)); + bmi=_mm_sub_ps(bmi,omi); + bmi=_mm_and_ps(bmi,_mm_load_ps((const float*)mask)); + __m128 t0(_mm_movehl_ps(ami,ami)); + ami=_mm_add_ps(ami,t0); + ami=_mm_add_ss(ami,_mm_shuffle_ps(ami,ami,1)); + __m128 t1(_mm_movehl_ps(bmi,bmi)); + bmi=_mm_add_ps(bmi,t1); + bmi=_mm_add_ss(bmi,_mm_shuffle_ps(bmi,bmi,1)); + return(_mm_cmple_ss(bmi,ami).m128_u32[0]&1); + #else + DBVT_ALIGN __int32 r[1]; + __asm + { + mov eax,o + mov ecx,a + mov edx,b + movaps xmm0,[eax] + movaps xmm5,mask + addps xmm0,[eax+16] + movaps xmm1,[ecx] + movaps xmm2,[edx] + addps xmm1,[ecx+16] + addps xmm2,[edx+16] + subps xmm1,xmm0 + subps xmm2,xmm0 + andps xmm1,xmm5 + andps xmm2,xmm5 + movhlps xmm3,xmm1 + movhlps xmm4,xmm2 + addps xmm1,xmm3 + addps xmm2,xmm4 + pshufd xmm3,xmm1,1 + pshufd xmm4,xmm2,1 + addss xmm1,xmm3 + addss xmm2,xmm4 + cmpless xmm2,xmm1 + movss r,xmm2 + } + return(r[0]&1); + #endif #else return(Proximity(o,a)treshold) { @@ -838,12 +844,13 @@ collideTT(root0,root1,xform,policy); // DBVT_PREFIX inline void btDbvt::collideTV( const btDbvtNode* root, - const btDbvtVolume& volume, + const btDbvtVolume& vol, DBVT_IPOLICY) { DBVT_CHECKTYPE if(root) { + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume(vol); btAlignedObjectArray stack; stack.reserve(SIMPLE_STACKSIZE); stack.push_back(root); @@ -1095,7 +1102,10 @@ if(root) #undef DBVT_IPOLICY #undef DBVT_CHECKTYPE #undef DBVT_IMPL_GENERIC -#undef DBVT_IMPL_FPU0x86 #undef DBVT_IMPL_SSE +#undef DBVT_USE_INTRINSIC_SSE +#undef DBVT_SELECT_IMPL +#undef DBVT_MERGE_IMPL +#undef DBVT_INT0_IMPL #endif diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp index 2d27f22567f..a57952ffa06 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.cpp @@ -55,17 +55,15 @@ btSimpleBroadphase::btSimpleBroadphase(int maxProxies, btOverlappingPairCache* o m_maxHandles = maxProxies; m_numHandles = 0; m_firstFreeHandle = 0; - m_firstAllocatedHandle = -1; + { for (int i = m_firstFreeHandle; i < maxProxies; i++) { m_pHandles[i].SetNextFree(i + 1); m_pHandles[i].m_uniqueId = i+2;//any UID will do, we just avoid too trivial values (0,1) for debugging purposes - m_pHandles[i].SetNextAllocated(-1); } m_pHandles[maxProxies - 1].SetNextFree(0); - m_pHandles[maxProxies - 1].SetNextAllocated(-1); } @@ -179,31 +177,29 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) //first check for new overlapping pairs int i,j; - if (m_firstAllocatedHandle >= 0) + if (m_numHandles >= 0) { - btSimpleBroadphaseProxy* proxy0 = &m_pHandles[m_firstAllocatedHandle]; - for (i=0;ifindPair(proxy0,proxy1)) - { - m_pairCache->addOverlappingPair(proxy0,proxy1); - } - } else + btSimpleBroadphaseProxy* p0 = getSimpleProxyFromProxy(proxy0); + btSimpleBroadphaseProxy* p1 = getSimpleProxyFromProxy(proxy1); + + if (aabbOverlap(p0,p1)) + { + if ( !m_pairCache->findPair(proxy0,proxy1)) { + m_pairCache->addOverlappingPair(proxy0,proxy1); + } + } else + { if (!m_pairCache->hasDeferredRemoval()) { if ( m_pairCache->findPair(proxy0,proxy1)) @@ -211,19 +207,13 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) m_pairCache->removeOverlappingPair(proxy0,proxy1,dispatcher); } } - - } } - proxy1 = &m_pHandles[proxy1->GetNextAllocated()]; - } - proxy0 = &m_pHandles[proxy0->GetNextAllocated()]; - } if (m_ownsPairCache && m_pairCache->hasDeferredRemoval()) { - + btBroadphasePairArray& overlappingPairArray = m_pairCache->getOverlappingPairArray(); //perform a sort, to find duplicates and to sort 'invalid' pairs to the end @@ -237,11 +227,11 @@ void btSimpleBroadphase::calculateOverlappingPairs(btDispatcher* dispatcher) previousPair.m_pProxy0 = 0; previousPair.m_pProxy1 = 0; previousPair.m_algorithm = 0; - - + + for (i=0;icleanOverlappingPair(pair,dispatcher); - // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); - // m_overlappingPairArray.pop_back(); + // m_overlappingPairArray.swap(i,m_overlappingPairArray.size()-1); + // m_overlappingPairArray.pop_back(); pair.m_pProxy0 = 0; pair.m_pProxy1 = 0; m_invalidPair++; gOverlappingPairs--; } - + } - ///if you don't like to skip the invalid pairs in the array, execute following code: - #define CLEAN_INVALID_PAIRS 1 - #ifdef CLEAN_INVALID_PAIRS + ///if you don't like to skip the invalid pairs in the array, execute following code: +#define CLEAN_INVALID_PAIRS 1 +#ifdef CLEAN_INVALID_PAIRS //perform a sort, to sort 'invalid' pairs to the end overlappingPairArray.quickSort(btBroadphasePairSortPredicate()); overlappingPairArray.resize(overlappingPairArray.size() - m_invalidPair); m_invalidPair = 0; - #endif//CLEAN_INVALID_PAIRS +#endif//CLEAN_INVALID_PAIRS } } diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h index 49dfeb84900..e2ebb825725 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btSimpleBroadphase.h @@ -25,7 +25,7 @@ struct btSimpleBroadphaseProxy : public btBroadphaseProxy btVector3 m_min; btVector3 m_max; int m_nextFree; - int m_nextAllocated; + // int m_handleId; @@ -42,8 +42,7 @@ struct btSimpleBroadphaseProxy : public btBroadphaseProxy SIMD_FORCE_INLINE void SetNextFree(int next) {m_nextFree = next;} SIMD_FORCE_INLINE int GetNextFree() const {return m_nextFree;} - SIMD_FORCE_INLINE void SetNextAllocated(int next) {m_nextAllocated = next;} - SIMD_FORCE_INLINE int GetNextAllocated() const {return m_nextAllocated;} + }; @@ -57,22 +56,18 @@ protected: int m_numHandles; // number of active handles int m_maxHandles; // max number of handles + btSimpleBroadphaseProxy* m_pHandles; // handles pool + void* m_pHandlesRawPtr; int m_firstFreeHandle; // free handles list - int m_firstAllocatedHandle; - + int allocHandle() { - + btAssert(m_numHandles < m_maxHandles); int freeHandle = m_firstFreeHandle; m_firstFreeHandle = m_pHandles[freeHandle].GetNextFree(); - - m_pHandles[freeHandle].SetNextAllocated(m_firstAllocatedHandle); - m_firstAllocatedHandle = freeHandle; - m_numHandles++; - return freeHandle; } @@ -84,13 +79,9 @@ protected: proxy->SetNextFree(m_firstFreeHandle); m_firstFreeHandle = handle; - m_firstAllocatedHandle = proxy->GetNextAllocated(); - proxy->SetNextAllocated(-1); - m_numHandles--; } - btOverlappingPairCache* m_pairCache; bool m_ownsPairCache; diff --git a/extern/bullet2/src/BulletCollision/CMakeLists.txt b/extern/bullet2/src/BulletCollision/CMakeLists.txt index e565bf7edea..d77ca6444c7 100644 --- a/extern/bullet2/src/BulletCollision/CMakeLists.txt +++ b/extern/bullet2/src/BulletCollision/CMakeLists.txt @@ -5,56 +5,149 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src } ADD_LIBRARY(LibBulletCollision BroadphaseCollision/btAxisSweep3.cpp + BroadphaseCollision/btAxisSweep3.h BroadphaseCollision/btBroadphaseProxy.cpp + BroadphaseCollision/btBroadphaseProxy.h BroadphaseCollision/btCollisionAlgorithm.cpp + BroadphaseCollision/btCollisionAlgorithm.h BroadphaseCollision/btDispatcher.cpp + BroadphaseCollision/btDispatcher.h + BroadphaseCollision/btDbvtBroadphase.cpp + BroadphaseCollision/btDbvtBroadphase.h + BroadphaseCollision/btDbvt.cpp + BroadphaseCollision/btDbvt.h + BroadphaseCollision/btMultiSapBroadphase.cpp + BroadphaseCollision/btMultiSapBroadphase.h BroadphaseCollision/btOverlappingPairCache.cpp + BroadphaseCollision/btOverlappingPairCache.h + BroadphaseCollision/btOverlappingPairCallback.h + BroadphaseCollision/btQuantizedBvh.cpp + BroadphaseCollision/btQuantizedBvh.h BroadphaseCollision/btSimpleBroadphase.cpp + BroadphaseCollision/btSimpleBroadphase.h CollisionDispatch/btCollisionDispatcher.cpp + CollisionDispatch/btCollisionDispatcher.h CollisionDispatch/btCollisionObject.cpp + CollisionDispatch/btCollisionObject.h CollisionDispatch/btCollisionWorld.cpp + CollisionDispatch/btCollisionWorld.h CollisionDispatch/btCompoundCollisionAlgorithm.cpp + CollisionDispatch/btCompoundCollisionAlgorithm.h CollisionDispatch/btConvexConcaveCollisionAlgorithm.cpp + CollisionDispatch/btConvexConcaveCollisionAlgorithm.h + CollisionDispatch/btDefaultCollisionConfiguration.cpp + CollisionDispatch/btDefaultCollisionConfiguration.h CollisionDispatch/btSphereSphereCollisionAlgorithm.cpp + CollisionDispatch/btSphereSphereCollisionAlgorithm.h + CollisionDispatch/btBoxBoxCollisionAlgorithm.cpp + CollisionDispatch/btBoxBoxCollisionAlgorithm.h + CollisionDispatch/btBoxBoxDetector.cpp + CollisionDispatch/btBoxBoxDetector.h CollisionDispatch/btSphereBoxCollisionAlgorithm.cpp + CollisionDispatch/btSphereBoxCollisionAlgorithm.h + CollisionDispatch/btConvexPlaneCollisionAlgorithm.cpp + CollisionDispatch/btConvexPlaneCollisionAlgorithm.h + CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp + CollisionDispatch/btSphereTriangleCollisionAlgorithm.h CollisionDispatch/btConvexConvexAlgorithm.cpp + CollisionDispatch/btConvexConvexAlgorithm.h CollisionDispatch/btEmptyCollisionAlgorithm.cpp + CollisionDispatch/btEmptyCollisionAlgorithm.h CollisionDispatch/btManifoldResult.cpp + CollisionDispatch/btManifoldResult.h CollisionDispatch/btSimulationIslandManager.cpp + CollisionDispatch/btSimulationIslandManager.h CollisionDispatch/btUnionFind.cpp + CollisionDispatch/btUnionFind.h + CollisionDispatch/SphereTriangleDetector.cpp + CollisionDispatch/SphereTriangleDetector.h CollisionShapes/btBoxShape.cpp + CollisionShapes/btBoxShape.h CollisionShapes/btBvhTriangleMeshShape.cpp + CollisionShapes/btBvhTriangleMeshShape.h + CollisionShapes/btCapsuleShape.cpp + CollisionShapes/btCapsuleShape.h CollisionShapes/btCollisionShape.cpp + CollisionShapes/btCollisionShape.h CollisionShapes/btCompoundShape.cpp + CollisionShapes/btCompoundShape.h CollisionShapes/btConcaveShape.cpp + CollisionShapes/btConcaveShape.h CollisionShapes/btConeShape.cpp + CollisionShapes/btConeShape.h CollisionShapes/btConvexHullShape.cpp + CollisionShapes/btConvexHullShape.h CollisionShapes/btConvexShape.cpp + CollisionShapes/btConvexShape.h + CollisionShapes/btConvexInternalShape.cpp + CollisionShapes/btConvexInternalShape.h CollisionShapes/btConvexTriangleMeshShape.cpp + CollisionShapes/btConvexTriangleMeshShape.h CollisionShapes/btCylinderShape.cpp + CollisionShapes/btCylinderShape.h CollisionShapes/btEmptyShape.cpp + CollisionShapes/btEmptyShape.h + CollisionShapes/btHeightfieldTerrainShape.cpp + CollisionShapes/btHeightfieldTerrainShape.h CollisionShapes/btMinkowskiSumShape.cpp + CollisionShapes/btMinkowskiSumShape.h + CollisionShapes/btMaterial.h + CollisionShapes/btMultimaterialTriangleMeshShape.cpp + CollisionShapes/btMultimaterialTriangleMeshShape.h CollisionShapes/btMultiSphereShape.cpp + CollisionShapes/btMultiSphereShape.h CollisionShapes/btOptimizedBvh.cpp + CollisionShapes/btOptimizedBvh.h CollisionShapes/btPolyhedralConvexShape.cpp + CollisionShapes/btPolyhedralConvexShape.h + CollisionShapes/btScaledBvhTriangleMeshShape.cpp + CollisionShapes/btScaledBvhTriangleMeshShape.h CollisionShapes/btTetrahedronShape.cpp + CollisionShapes/btTetrahedronShape.h CollisionShapes/btSphereShape.cpp + CollisionShapes/btSphereShape.h + CollisionShapes/btShapeHull.h + CollisionShapes/btShapeHull.cpp CollisionShapes/btStaticPlaneShape.cpp + CollisionShapes/btStaticPlaneShape.h CollisionShapes/btStridingMeshInterface.cpp + CollisionShapes/btStridingMeshInterface.h CollisionShapes/btTriangleCallback.cpp + CollisionShapes/btTriangleCallback.h CollisionShapes/btTriangleBuffer.cpp + CollisionShapes/btTriangleBuffer.h CollisionShapes/btTriangleIndexVertexArray.cpp + CollisionShapes/btTriangleIndexVertexArray.h + CollisionShapes/btTriangleIndexVertexMaterialArray.h + CollisionShapes/btTriangleIndexVertexMaterialArray.cpp CollisionShapes/btTriangleMesh.cpp + CollisionShapes/btTriangleMesh.h CollisionShapes/btTriangleMeshShape.cpp + CollisionShapes/btTriangleMeshShape.h + CollisionShapes/btUniformScalingShape.cpp + CollisionShapes/btUniformScalingShape.h NarrowPhaseCollision/btContinuousConvexCollision.cpp + NarrowPhaseCollision/btContinuousConvexCollision.h NarrowPhaseCollision/btGjkEpa.cpp + NarrowPhaseCollision/btGjkEpa.h + NarrowPhaseCollision/btGjkEpa2.cpp + NarrowPhaseCollision/btGjkEpa2.h NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.cpp + NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h NarrowPhaseCollision/btConvexCast.cpp + NarrowPhaseCollision/btConvexCast.h NarrowPhaseCollision/btGjkConvexCast.cpp + NarrowPhaseCollision/btGjkConvexCast.h NarrowPhaseCollision/btGjkPairDetector.cpp + NarrowPhaseCollision/btGjkPairDetector.h NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.cpp + NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h NarrowPhaseCollision/btPersistentManifold.cpp + NarrowPhaseCollision/btPersistentManifold.h NarrowPhaseCollision/btRaycastCallback.cpp + NarrowPhaseCollision/btRaycastCallback.h NarrowPhaseCollision/btSubSimplexConvexCast.cpp + NarrowPhaseCollision/btSubSimplexConvexCast.h NarrowPhaseCollision/btVoronoiSimplexSolver.cpp + NarrowPhaseCollision/btVoronoiSimplexSolver.h ) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp index e55604632c0..45ebff5dc45 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btBoxBoxDetector.cpp @@ -226,7 +226,7 @@ void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]) a = btScalar(j)*(2*M__PI/m) + A[i0]; if (a > M__PI) a -= 2*M__PI; btScalar maxdiff=1e9,diff; -#ifndef dNODEBUG +#if defined(DEBUG) || defined (_DEBUG) *iret = i0; // iret is not allowed to keep this value #endif for (i=0; igetCollisionShape()->getAabb(colObj->getWorldTransform(), minAabb,maxAabb); + //need to increase the aabb for contact thresholds + btVector3 contactThreshold(gContactBreakingThreshold,gContactBreakingThreshold,gContactBreakingThreshold); + minAabb -= contactThreshold; + maxAabb += contactThreshold; + btBroadphaseInterface* bp = (btBroadphaseInterface*)m_broadphasePairCache; //moving objects should be moderately sized, probably something wrong if not @@ -381,14 +386,14 @@ void btCollisionWorld::rayTestSingle(const btTransform& rayFromTrans,const btTra btTransform childWorldTrans = colObjWorldTransform * childTrans; // replace collision shape so that callback can determine the triangle btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape(); - collisionObject->setCollisionShape((btCollisionShape*)childCollisionShape); + collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape); rayTestSingle(rayFromTrans,rayToTrans, collisionObject, childCollisionShape, childWorldTrans, resultCallback); // restore - collisionObject->setCollisionShape(saveCollisionShape); + collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape); } } } @@ -577,14 +582,14 @@ void btCollisionWorld::objectQuerySingle(const btConvexShape* castShape,const bt btTransform childWorldTrans = colObjWorldTransform * childTrans; // replace collision shape so that callback can determine the triangle btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape(); - collisionObject->setCollisionShape((btCollisionShape*)childCollisionShape); + collisionObject->internalSetTemporaryCollisionShape((btCollisionShape*)childCollisionShape); objectQuerySingle(castShape, convexFromTrans,convexToTrans, collisionObject, childCollisionShape, childWorldTrans, resultCallback, allowedPenetration); // restore - collisionObject->setCollisionShape(saveCollisionShape); + collisionObject->internalSetTemporaryCollisionShape(saveCollisionShape); } } } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp index a29a6d624e5..da9336c55c7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp @@ -16,12 +16,17 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h" #include "BulletCollision/CollisionDispatch/btCollisionObject.h" #include "BulletCollision/CollisionShapes/btCompoundShape.h" - +#include "BulletCollision/BroadphaseCollision/btDbvt.h" +#include "LinearMath/btIDebugDraw.h" +#include "LinearMath/btAabbUtil2.h" btCompoundCollisionAlgorithm::btCompoundCollisionAlgorithm( const btCollisionAlgorithmConstructionInfo& ci,btCollisionObject* body0,btCollisionObject* body1,bool isSwapped) :btCollisionAlgorithm(ci), -m_isSwapped(isSwapped) +m_isSwapped(isSwapped), +m_sharedManifold(ci.m_manifold) { + m_ownsManifold = false; + btCollisionObject* colObj = m_isSwapped? body1 : body0; btCollisionObject* otherObj = m_isSwapped? body0 : body1; assert (colObj->getCollisionShape()->isCompound()); @@ -33,11 +38,17 @@ m_isSwapped(isSwapped) m_childCollisionAlgorithms.resize(numChildren); for (i=0;igetCollisionShape(); - btCollisionShape* childShape = compoundShape->getChildShape(i); - colObj->internalSetTemporaryCollisionShape( childShape ); - m_childCollisionAlgorithms[i] = ci.m_dispatcher1->findAlgorithm(colObj,otherObj); - colObj->internalSetTemporaryCollisionShape( tmpShape ); + if (compoundShape->getDynamicAabbTree()) + { + m_childCollisionAlgorithms[i] = 0; + } else + { + btCollisionShape* tmpShape = colObj->getCollisionShape(); + btCollisionShape* childShape = compoundShape->getChildShape(i); + colObj->internalSetTemporaryCollisionShape( childShape ); + m_childCollisionAlgorithms[i] = ci.m_dispatcher1->findAlgorithm(colObj,otherObj,m_sharedManifold); + colObj->internalSetTemporaryCollisionShape( tmpShape ); + } } } @@ -48,11 +59,109 @@ btCompoundCollisionAlgorithm::~btCompoundCollisionAlgorithm() int i; for (i=0;i~btCollisionAlgorithm(); - m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); + if (m_childCollisionAlgorithms[i]) + { + m_childCollisionAlgorithms[i]->~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); + } } } + + + +struct btCompoundLeafCallback : btDbvt::ICollide +{ + +public: + + btCollisionObject* m_compoundColObj; + btCollisionObject* m_otherObj; + btDispatcher* m_dispatcher; + const btDispatcherInfo& m_dispatchInfo; + btManifoldResult* m_resultOut; + btCollisionAlgorithm** m_childCollisionAlgorithms; + btPersistentManifold* m_sharedManifold; + + + + + btCompoundLeafCallback (btCollisionObject* compoundObj,btCollisionObject* otherObj,btDispatcher* dispatcher,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut,btCollisionAlgorithm** childCollisionAlgorithms,btPersistentManifold* sharedManifold) + :m_compoundColObj(compoundObj),m_otherObj(otherObj),m_dispatcher(dispatcher),m_dispatchInfo(dispatchInfo),m_resultOut(resultOut), + m_childCollisionAlgorithms(childCollisionAlgorithms), + m_sharedManifold(sharedManifold) + { + + } + + + void ProcessChildShape(btCollisionShape* childShape,int index) + { + + btCompoundShape* compoundShape = static_cast(m_compoundColObj->getCollisionShape()); + + + //backup + btTransform orgTrans = m_compoundColObj->getWorldTransform(); + btTransform orgInterpolationTrans = m_compoundColObj->getInterpolationWorldTransform(); + const btTransform& childTrans = compoundShape->getChildTransform(index); + btTransform newChildWorldTrans = orgTrans*childTrans ; + + //perform an AABB check first + btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; + childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0); + m_otherObj->getCollisionShape()->getAabb(m_otherObj->getWorldTransform(),aabbMin1,aabbMax1); + + if (TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) + { + + m_compoundColObj->setWorldTransform( newChildWorldTrans); + m_compoundColObj->setInterpolationWorldTransform(newChildWorldTrans); + + //the contactpoint is still projected back using the original inverted worldtrans + btCollisionShape* tmpShape = m_compoundColObj->getCollisionShape(); + m_compoundColObj->internalSetTemporaryCollisionShape( childShape ); + + if (!m_childCollisionAlgorithms[index]) + m_childCollisionAlgorithms[index] = m_dispatcher->findAlgorithm(m_compoundColObj,m_otherObj,m_sharedManifold); + + m_childCollisionAlgorithms[index]->processCollision(m_compoundColObj,m_otherObj,m_dispatchInfo,m_resultOut); + if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + btVector3 worldAabbMin,worldAabbMax; + m_dispatchInfo.m_debugDraw->drawAabb(aabbMin0,aabbMax0,btVector3(1,1,1)); + m_dispatchInfo.m_debugDraw->drawAabb(aabbMin1,aabbMax1,btVector3(1,1,1)); + } + + //revert back transform + m_compoundColObj->internalSetTemporaryCollisionShape( tmpShape); + m_compoundColObj->setWorldTransform( orgTrans ); + m_compoundColObj->setInterpolationWorldTransform(orgInterpolationTrans); + } + } + void Process(const btDbvtNode* leaf) + { + int index = int(leaf->data); + + btCompoundShape* compoundShape = static_cast(m_compoundColObj->getCollisionShape()); + btCollisionShape* childShape = compoundShape->getChildShape(index); + if (m_dispatchInfo.m_debugDraw && (m_dispatchInfo.m_debugDraw->getDebugMode() & btIDebugDraw::DBG_DrawAabb)) + { + btVector3 worldAabbMin,worldAabbMax; + btTransform orgTrans = m_compoundColObj->getWorldTransform(); + btTransformAabb(leaf->volume.Mins(),leaf->volume.Maxs(),0.,orgTrans,worldAabbMin,worldAabbMax); + m_dispatchInfo.m_debugDraw->drawAabb(worldAabbMin,worldAabbMax,btVector3(1,0,0)); + } + ProcessChildShape(childShape,index); + + } +}; + + + + + + void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,btCollisionObject* body1,const btDispatcherInfo& dispatchInfo,btManifoldResult* resultOut) { btCollisionObject* colObj = m_isSwapped? body1 : body0; @@ -61,37 +170,69 @@ void btCompoundCollisionAlgorithm::processCollision (btCollisionObject* body0,bt assert (colObj->getCollisionShape()->isCompound()); btCompoundShape* compoundShape = static_cast(colObj->getCollisionShape()); - //We will use the OptimizedBVH, AABB tree to cull potential child-overlaps - //If both proxies are Compound, we will deal with that directly, by performing sequential/parallel tree traversals - //given Proxy0 and Proxy1, if both have a tree, Tree0 and Tree1, this means: - //determine overlapping nodes of Proxy1 using Proxy0 AABB against Tree1 - //then use each overlapping node AABB against Tree0 - //and vise versa. + btDbvt* tree = compoundShape->getDynamicAabbTree(); + //use a dynamic aabb tree to cull potential child-overlaps + btCompoundLeafCallback callback(colObj,otherObj,m_dispatcher,dispatchInfo,resultOut,&m_childCollisionAlgorithms[0],m_sharedManifold); - int numChildren = m_childCollisionAlgorithms.size(); - int i; - for (i=0;igetChildShape(i); - //backup - btTransform orgTrans = colObj->getWorldTransform(); - btTransform orgInterpolationTrans = colObj->getInterpolationWorldTransform(); + btVector3 localAabbMin,localAabbMax; + btTransform otherInCompoundSpace; + otherInCompoundSpace = colObj->getWorldTransform().inverse() * otherObj->getWorldTransform(); + otherObj->getCollisionShape()->getAabb(otherInCompoundSpace,localAabbMin,localAabbMax); - const btTransform& childTrans = compoundShape->getChildTransform(i); - btTransform newChildWorldTrans = orgTrans*childTrans ; - colObj->setWorldTransform( newChildWorldTrans); - colObj->setInterpolationWorldTransform(newChildWorldTrans); + const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); + //process all children, that overlap with the given AABB bounds + tree->collideTV(tree->m_root,bounds,callback); + + } else + { + //iterate over all children, perform an AABB check inside ProcessChildShape + int numChildren = m_childCollisionAlgorithms.size(); + int i; + for (i=0;igetChildShape(i),i); + } + } + + { + //iterate over all children, perform an AABB check inside ProcessChildShape + int numChildren = m_childCollisionAlgorithms.size(); + int i; + btManifoldArray manifoldArray; + + for (i=0;igetChildShape(i); + //if not longer overlapping, remove the algorithm + btTransform orgTrans = colObj->getWorldTransform(); + btTransform orgInterpolationTrans = colObj->getInterpolationWorldTransform(); + const btTransform& childTrans = compoundShape->getChildTransform(i); + btTransform newChildWorldTrans = orgTrans*childTrans ; + + //perform an AABB check first + btVector3 aabbMin0,aabbMax0,aabbMin1,aabbMax1; + childShape->getAabb(newChildWorldTrans,aabbMin0,aabbMax0); + otherObj->getCollisionShape()->getAabb(otherObj->getWorldTransform(),aabbMin1,aabbMax1); + + if (!TestAabbAgainstAabb2(aabbMin0,aabbMax0,aabbMin1,aabbMax1)) + { + m_childCollisionAlgorithms[i]->~btCollisionAlgorithm(); + m_dispatcher->freeCollisionAlgorithm(m_childCollisionAlgorithms[i]); + m_childCollisionAlgorithms[i] = 0; + } + + } + + } + + - //the contactpoint is still projected back using the original inverted worldtrans - btCollisionShape* tmpShape = colObj->getCollisionShape(); - colObj->internalSetTemporaryCollisionShape( childShape ); - m_childCollisionAlgorithms[i]->processCollision(colObj,otherObj,dispatchInfo,resultOut); - //revert back - colObj->internalSetTemporaryCollisionShape( tmpShape); - colObj->setWorldTransform( orgTrans ); - colObj->setInterpolationWorldTransform(orgInterpolationTrans); } } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h index 1682c6761cd..624a3cf10f5 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.h @@ -28,11 +28,13 @@ class btDispatcher; class btDispatcher; /// btCompoundCollisionAlgorithm supports collision between CompoundCollisionShapes and other collision shapes -/// Place holder, not fully implemented yet class btCompoundCollisionAlgorithm : public btCollisionAlgorithm { btAlignedObjectArray m_childCollisionAlgorithms; bool m_isSwapped; + + class btPersistentManifold* m_sharedManifold; + bool m_ownsManifold; public: @@ -49,7 +51,8 @@ public: int i; for (i=0;igetAllContactManifolds(manifoldArray); + if (m_childCollisionAlgorithms[i]) + m_childCollisionAlgorithms[i]->getAllContactManifolds(manifoldArray); } } diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp index 3f94f4d4eac..1c317080544 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.cpp @@ -22,7 +22,9 @@ subject to the following restrictions: #include "BulletCollision/CollisionDispatch/btConvexPlaneCollisionAlgorithm.h" #include "BulletCollision/CollisionDispatch/btBoxBoxCollisionAlgorithm.h" #include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM #include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM #include "BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.h" #include "BulletCollision/NarrowPhaseCollision/btGjkEpaPenetrationDepthSolver.h" #include "BulletCollision/NarrowPhaseCollision/btMinkowskiPenetrationDepthSolver.h" @@ -70,11 +72,14 @@ btDefaultCollisionConfiguration::btDefaultCollisionConfiguration(const btDefault mem = btAlignedAlloc(sizeof(btSphereSphereCollisionAlgorithm::CreateFunc),16); m_sphereSphereCF = new(mem) btSphereSphereCollisionAlgorithm::CreateFunc; +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); m_sphereBoxCF = new(mem) btSphereBoxCollisionAlgorithm::CreateFunc; mem = btAlignedAlloc(sizeof(btSphereBoxCollisionAlgorithm::CreateFunc),16); m_boxSphereCF = new (mem)btSphereBoxCollisionAlgorithm::CreateFunc; m_boxSphereCF->m_swapped = true; +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); m_sphereTriangleCF = new (mem)btSphereTriangleCollisionAlgorithm::CreateFunc; mem = btAlignedAlloc(sizeof(btSphereTriangleCollisionAlgorithm::CreateFunc),16); @@ -176,10 +181,13 @@ btDefaultCollisionConfiguration::~btDefaultCollisionConfiguration() m_sphereSphereCF->~btCollisionAlgorithmCreateFunc(); btAlignedFree( m_sphereSphereCF); +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM m_sphereBoxCF->~btCollisionAlgorithmCreateFunc(); btAlignedFree( m_sphereBoxCF); m_boxSphereCF->~btCollisionAlgorithmCreateFunc(); btAlignedFree( m_boxSphereCF); +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + m_sphereTriangleCF->~btCollisionAlgorithmCreateFunc(); btAlignedFree( m_sphereTriangleCF); m_triangleSphereCF->~btCollisionAlgorithmCreateFunc(); @@ -212,7 +220,7 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlg { return m_sphereSphereCF; } - +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE) && (proxyType1==BOX_SHAPE_PROXYTYPE)) { return m_sphereBoxCF; @@ -222,6 +230,8 @@ btCollisionAlgorithmCreateFunc* btDefaultCollisionConfiguration::getCollisionAlg { return m_boxSphereCF; } +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + if ((proxyType0 == SPHERE_SHAPE_PROXYTYPE ) && (proxyType1==TRIANGLE_SHAPE_PROXYTYPE)) { diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h index 0b274d394af..4f5af5f048c 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h @@ -71,8 +71,11 @@ class btDefaultCollisionConfiguration : public btCollisionConfiguration btCollisionAlgorithmCreateFunc* m_swappedCompoundCreateFunc; btCollisionAlgorithmCreateFunc* m_emptyCreateFunc; btCollisionAlgorithmCreateFunc* m_sphereSphereCF; +#ifdef USE_BUGGY_SPHERE_BOX_ALGORITHM btCollisionAlgorithmCreateFunc* m_sphereBoxCF; btCollisionAlgorithmCreateFunc* m_boxSphereCF; +#endif //USE_BUGGY_SPHERE_BOX_ALGORITHM + btCollisionAlgorithmCreateFunc* m_boxBoxCF; btCollisionAlgorithmCreateFunc* m_sphereTriangleCF; btCollisionAlgorithmCreateFunc* m_triangleSphereCF; diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp index 46961f5d61b..fdbd4abef27 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btSphereTriangleCollisionAlgorithm.cpp @@ -63,7 +63,7 @@ void btSphereTriangleCollisionAlgorithm::processCollision (btCollisionObject* co input.m_transformA = sphereObj->getWorldTransform(); input.m_transformB = triObj->getWorldTransform(); - bool swapResults = m_swapped && !m_ownManifold; + bool swapResults = m_swapped; detector.getClosestPoints(input,*resultOut,dispatchInfo.m_debugDraw,swapResults); diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp index adac455bbcb..8bc2cfa6ffa 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btBoxShape.cpp @@ -21,19 +21,7 @@ subject to the following restrictions: void btBoxShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const { - const btVector3& halfExtents = getHalfExtentsWithoutMargin(); - - btMatrix3x3 abs_b = t.getBasis().absolute(); - btPoint3 center = t.getOrigin(); - btVector3 extent = btVector3(abs_b[0].dot(halfExtents), - abs_b[1].dot(halfExtents), - abs_b[2].dot(halfExtents)); - extent += btVector3(getMargin(),getMargin(),getMargin()); - - aabbMin = center - extent; - aabbMax = center + extent; - - + btTransformAabb(getHalfExtentsWithoutMargin(),getMargin(),t,aabbMin,aabbMax); } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h index 92bcce55119..d4b046d40c9 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCapsuleShape.h @@ -49,10 +49,11 @@ public: { btVector3 halfExtents(getRadius(),getRadius(),getRadius()); halfExtents[m_upAxis] = getRadius() + getHalfHeight(); + halfExtents += btVector3(getMargin(),getMargin(),getMargin()); btMatrix3x3 abs_b = t.getBasis().absolute(); btPoint3 center = t.getOrigin(); btVector3 extent = btVector3(abs_b[0].dot(halfExtents),abs_b[1].dot(halfExtents),abs_b[2].dot(halfExtents)); - extent += btVector3(getMargin(),getMargin(),getMargin()); + aabbMin = center - extent; aabbMax = center + extent; } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp index 740f1783630..f08b810eadb 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.cpp @@ -14,23 +14,29 @@ subject to the following restrictions: */ #include "btCompoundShape.h" - - #include "btCollisionShape.h" - +#include "BulletCollision/BroadphaseCollision/btDbvt.h" btCompoundShape::btCompoundShape() :m_localAabbMin(btScalar(1e30),btScalar(1e30),btScalar(1e30)), m_localAabbMax(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)), -m_aabbTree(0), m_collisionMargin(btScalar(0.)), -m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)) +m_localScaling(btScalar(1.),btScalar(1.),btScalar(1.)), +m_dynamicAabbTree(0) { + void* mem = btAlignedAlloc(sizeof(btDbvt),16); + m_dynamicAabbTree = new(mem) btDbvt(); + btAssert(mem==m_dynamicAabbTree); } btCompoundShape::~btCompoundShape() { + if (m_dynamicAabbTree) + { + m_dynamicAabbTree->~btDbvt(); + btAlignedFree(m_dynamicAabbTree); + } } void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisionShape* shape) @@ -60,71 +66,88 @@ void btCompoundShape::addChildShape(const btTransform& localTransform,btCollisio } } + if (m_dynamicAabbTree) + { + const btDbvtVolume bounds=btDbvtVolume::FromMM(localAabbMin,localAabbMax); + int index = m_children.size()-1; + child.m_node = m_dynamicAabbTree->insert(bounds,(void*)index); + } + +} + +void btCompoundShape::removeChildShapeByIndex(int childShapeIndex) +{ + btAssert(childShapeIndex >=0 && childShapeIndex < m_children.size()); + if (m_dynamicAabbTree) + { + m_dynamicAabbTree->remove(m_children[childShapeIndex].m_node); + } + m_children.swap(childShapeIndex,m_children.size()-1); + m_children.pop_back(); + } void btCompoundShape::removeChildShape(btCollisionShape* shape) { - bool done_removing; - - // Find the children containing the shape specified, and remove those children. - do - { - done_removing = true; - - for(int i = 0; i < m_children.size(); i++) - { - if(m_children[i].m_childShape == shape) - { - m_children.remove(m_children[i]); - done_removing = false; // Do another iteration pass after removing from the vector - break; - } - } - } - while (!done_removing); - - recalculateLocalAabb(); + // Find the children containing the shape specified, and remove those children. + //note: there might be multiple children using the same shape! + for(int i = m_children.size()-1; i >= 0 ; i--) + { + if(m_children[i].m_childShape == shape) + { + m_children.swap(i,m_children.size()-1); + m_children.pop_back(); + //remove it from the m_dynamicAabbTree too + //m_dynamicAabbTree->remove(m_aabbProxies[i]); + //m_aabbProxies.swap(i,m_children.size()-1); + //m_aabbProxies.pop_back(); + } + } + + + + recalculateLocalAabb(); } void btCompoundShape::recalculateLocalAabb() { - // Recalculate the local aabb - // Brute force, it iterates over all the shapes left. - m_localAabbMin = btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30)); - m_localAabbMax = btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); - - //extend the local aabbMin/aabbMax - for (int j = 0; j < m_children.size(); j++) - { - btVector3 localAabbMin,localAabbMax; - m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax); - for (int i=0;i<3;i++) - { - if (m_localAabbMin[i] > localAabbMin[i]) - m_localAabbMin[i] = localAabbMin[i]; - if (m_localAabbMax[i] < localAabbMax[i]) - m_localAabbMax[i] = localAabbMax[i]; - } - } + // Recalculate the local aabb + // Brute force, it iterates over all the shapes left. + m_localAabbMin = btVector3(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + m_localAabbMax = btVector3(btScalar(-1e30),btScalar(-1e30),btScalar(-1e30)); + + //extend the local aabbMin/aabbMax + for (int j = 0; j < m_children.size(); j++) + { + btVector3 localAabbMin,localAabbMax; + m_children[j].m_childShape->getAabb(m_children[j].m_transform, localAabbMin, localAabbMax); + for (int i=0;i<3;i++) + { + if (m_localAabbMin[i] > localAabbMin[i]) + m_localAabbMin[i] = localAabbMin[i]; + if (m_localAabbMax[i] < localAabbMax[i]) + m_localAabbMax[i] = localAabbMax[i]; + } + } } - - ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version + +///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version void btCompoundShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const { btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); + localHalfExtents += btVector3(getMargin(),getMargin(),getMargin()); btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); - + btMatrix3x3 abs_b = trans.getBasis().absolute(); btPoint3 center = trans(localCenter); btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), - abs_b[1].dot(localHalfExtents), - abs_b[2].dot(localHalfExtents)); - extent += btVector3(getMargin(),getMargin(),getMargin()); + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + aabbMin = center-extent; + aabbMax = center+extent; - aabbMin = center - extent; - aabbMax = center + extent; } void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const @@ -134,9 +157,9 @@ void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) co ident.setIdentity(); btVector3 aabbMin,aabbMax; getAabb(ident,aabbMin,aabbMax); - + btVector3 halfExtents = (aabbMax-aabbMin)*btScalar(0.5); - + btScalar lx=btScalar(2.)*(halfExtents.x()); btScalar ly=btScalar(2.)*(halfExtents.y()); btScalar lz=btScalar(2.)*(halfExtents.z()); @@ -147,5 +170,62 @@ void btCompoundShape::calculateLocalInertia(btScalar mass,btVector3& inertia) co } - - + + + +void btCompoundShape::calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const +{ + int n = m_children.size(); + + btScalar totalMass = 0; + btVector3 center(0, 0, 0); + for (int k = 0; k < n; k++) + { + center += m_children[k].m_transform.getOrigin() * masses[k]; + totalMass += masses[k]; + } + center /= totalMass; + principal.setOrigin(center); + + btMatrix3x3 tensor(0, 0, 0, 0, 0, 0, 0, 0, 0); + for (int k = 0; k < n; k++) + { + btVector3 i; + m_children[k].m_childShape->calculateLocalInertia(masses[k], i); + + const btTransform& t = m_children[k].m_transform; + btVector3 o = t.getOrigin() - center; + + //compute inertia tensor in coordinate system of compound shape + btMatrix3x3 j = t.getBasis().transpose(); + j[0] *= i[0]; + j[1] *= i[1]; + j[2] *= i[2]; + j = t.getBasis() * j; + + //add inertia tensor + tensor[0] += j[0]; + tensor[1] += j[1]; + tensor[2] += j[2]; + + //compute inertia tensor of pointmass at o + btScalar o2 = o.length2(); + j[0].setValue(o2, 0, 0); + j[1].setValue(0, o2, 0); + j[2].setValue(0, 0, o2); + j[0] += o * -o.x(); + j[1] += o * -o.y(); + j[2] += o * -o.z(); + + //add inertia tensor of pointmass + tensor[0] += masses[k] * j[0]; + tensor[1] += masses[k] * j[1]; + tensor[2] += masses[k] * j[2]; + } + + tensor.diagonalize(principal.getBasis(), btScalar(0.00001), 20); + inertia.setValue(tensor[0][0], tensor[1][1], tensor[2][2]); +} + + + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h index f77e4b59558..3624749f768 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btCompoundShape.h @@ -24,8 +24,8 @@ subject to the following restrictions: #include "btCollisionMargin.h" #include "LinearMath/btAlignedObjectArray.h" -class btOptimizedBvh; - +//class btOptimizedBvh; +struct btDbvt; ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild { @@ -35,14 +35,15 @@ ATTRIBUTE_ALIGNED16(struct) btCompoundShapeChild btCollisionShape* m_childShape; int m_childShapeType; btScalar m_childMargin; + struct btDbvtNode* m_node; }; SIMD_FORCE_INLINE bool operator==(const btCompoundShapeChild& c1, const btCompoundShapeChild& c2) { - return ( c1.m_transform == c2.m_transform && - c1.m_childShape == c2.m_childShape && - c1.m_childShapeType == c2.m_childShapeType && - c1.m_childMargin == c2.m_childMargin ); + return ( c1.m_transform == c2.m_transform && + c1.m_childShape == c2.m_childShape && + c1.m_childShapeType == c2.m_childShapeType && + c1.m_childMargin == c2.m_childMargin ); } /// btCompoundShape allows to store multiple other btCollisionShapes @@ -55,7 +56,8 @@ ATTRIBUTE_ALIGNED16(class) btCompoundShape : public btCollisionShape btVector3 m_localAabbMin; btVector3 m_localAabbMax; - btOptimizedBvh* m_aabbTree; + //btOptimizedBvh* m_aabbTree; + btDbvt* m_dynamicAabbTree; public: BT_DECLARE_ALIGNED_ALLOCATOR(); @@ -66,11 +68,11 @@ public: void addChildShape(const btTransform& localTransform,btCollisionShape* shape); - /** Remove all children shapes that contain the specified shape. */ + /// Remove all children shapes that contain the specified shape virtual void removeChildShape(btCollisionShape* shape); - - + void removeChildShapeByIndex(int childShapeindex); + int getNumChildShapes() const { @@ -103,9 +105,9 @@ public: ///getAabb's default implementation is brute force, expected derived classes to implement a fast dedicated version virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; - - /** Re-calculate the local Aabb. Is called at the end of removeChildShapes. - Use this yourself if you modify the children or their transforms. */ + + /** Re-calculate the local Aabb. Is called at the end of removeChildShapes. + Use this yourself if you modify the children or their transforms. */ virtual void recalculateLocalAabb(); virtual void setLocalScaling(const btVector3& scaling) @@ -118,7 +120,7 @@ public: } virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; - + virtual int getShapeType() const { return COMPOUND_SHAPE_PROXYTYPE;} virtual void setMargin(btScalar margin) @@ -137,11 +139,19 @@ public: //this is optional, but should make collision queries faster, by culling non-overlapping nodes void createAabbTreeFromChildren(); - const btOptimizedBvh* getAabbTree() const + btDbvt* getDynamicAabbTree() { - return m_aabbTree; + return m_dynamicAabbTree; } + ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia + ///and the center of mass to the current coordinate system. "masses" points to an array of masses of the children. The resulting transform + ///"principal" has to be applied inversely to all children transforms in order for the local coordinate system of the compound + ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform + ///of the collision object by the principal transform. + void calculatePrincipalAxisTransform(btScalar* masses, btTransform& principal, btVector3& inertia) const; + + private: btScalar m_collisionMargin; protected: diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp index f1682aaf65b..02a293e82ba 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.cpp @@ -204,3 +204,113 @@ const btVector3& btConvexTriangleMeshShape::getLocalScaling() const { return m_stridingMesh->getScaling(); } + +void btConvexTriangleMeshShape::calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const +{ + class CenterCallback: public btInternalTriangleIndexCallback + { + bool first; + btVector3 ref; + btVector3 sum; + btScalar volume; + + public: + + CenterCallback() : first(true), ref(0, 0, 0), sum(0, 0, 0), volume(0) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) + { + (void) triangleIndex; + (void) partId; + if (first) + { + ref = triangle[0]; + first = false; + } + else + { + btScalar vol = btFabs((triangle[0] - ref).triple(triangle[1] - ref, triangle[2] - ref)); + sum += (btScalar(0.25) * vol) * ((triangle[0] + triangle[1] + triangle[2] + ref)); + volume += vol; + } + } + + btVector3 getCenter() + { + return (volume > 0) ? sum / volume : ref; + } + + btScalar getVolume() + { + return volume * btScalar(1. / 6); + } + + }; + + class InertiaCallback: public btInternalTriangleIndexCallback + { + btMatrix3x3 sum; + btVector3 center; + + public: + + InertiaCallback(btVector3& center) : sum(0, 0, 0, 0, 0, 0, 0, 0, 0), center(center) + { + } + + virtual void internalProcessTriangleIndex(btVector3* triangle, int partId, int triangleIndex) + { + (void) triangleIndex; + (void) partId; + btMatrix3x3 i; + btVector3 a = triangle[0] - center; + btVector3 b = triangle[1] - center; + btVector3 c = triangle[2] - center; + btVector3 abc = a + b + c; + btScalar volNeg = -btFabs(a.triple(b, c)) * btScalar(1. / 6); + for (int j = 0; j < 3; j++) + { + for (int k = 0; k <= j; k++) + { + i[j][k] = i[k][j] = volNeg * (center[j] * center[k] + + btScalar(0.25) * (center[j] * abc[k] + center[k] * abc[j]) + + btScalar(0.1) * (a[j] * a[k] + b[j] * b[k] + c[j] * c[k]) + + btScalar(0.05) * (a[j] * b[k] + a[k] * b[j] + a[j] * c[k] + a[k] * c[j] + b[j] * c[k] + b[k] * c[j])); + } + } + btScalar i00 = -i[0][0]; + btScalar i11 = -i[1][1]; + btScalar i22 = -i[2][2]; + i[0][0] = i11 + i22; + i[1][1] = i22 + i00; + i[2][2] = i00 + i11; + sum[0] += i[0]; + sum[1] += i[1]; + sum[2] += i[2]; + } + + btMatrix3x3& getInertia() + { + return sum; + } + + }; + + CenterCallback centerCallback; + btVector3 aabbMax(btScalar(1e30),btScalar(1e30),btScalar(1e30)); + m_stridingMesh->InternalProcessAllTriangles(¢erCallback, -aabbMax, aabbMax); + btVector3 center = centerCallback.getCenter(); + principal.setOrigin(center); + volume = centerCallback.getVolume(); + + InertiaCallback inertiaCallback(center); + m_stridingMesh->InternalProcessAllTriangles(&inertiaCallback, -aabbMax, aabbMax); + + btMatrix3x3& i = inertiaCallback.getInertia(); + i.diagonalize(principal.getBasis(), btScalar(0.00001), 20); + inertia.setValue(i[0][0], i[1][1], i[2][2]); + inertia /= volume; +} + diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h index 01eecf27811..6ff0bf5d43b 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btConvexTriangleMeshShape.h @@ -46,6 +46,13 @@ public: virtual void setLocalScaling(const btVector3& scaling); virtual const btVector3& getLocalScaling() const; + ///computes the exact moment of inertia and the transform from the coordinate system defined by the principal axes of the moment of inertia + ///and the center of mass to the current coordinate system. A mass of 1 is assumed, for other masses just multiply the computed "inertia" + ///by the mass. The resulting transform "principal" has to be applied inversely to the mesh in order for the local coordinate system of the + ///shape to be centered at the center of mass and to coincide with the principal axes. This also necessitates a correction of the world transform + ///of the collision object by the principal transform. This method also computes the volume of the convex mesh. + void calculatePrincipalAxisTransform(btTransform& principal, btVector3& inertia, btScalar& volume) const; + }; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp index 9e4800a46fe..a291d6b7ce7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btHeightfieldTerrainShape.cpp @@ -91,19 +91,15 @@ btHeightfieldTerrainShape::~btHeightfieldTerrainShape() void btHeightfieldTerrainShape::getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const { -/* - aabbMin.setValue(-1e30f,-1e30f,-1e30f); - aabbMax.setValue(1e30f,1e30f,1e30f); -*/ - btVector3 halfExtents = (m_localAabbMax-m_localAabbMin)* m_localScaling * btScalar(0.5); + halfExtents += btVector3(getMargin(),getMargin(),getMargin()); btMatrix3x3 abs_b = t.getBasis().absolute(); btPoint3 center = t.getOrigin(); btVector3 extent = btVector3(abs_b[0].dot(halfExtents), abs_b[1].dot(halfExtents), abs_b[2].dot(halfExtents)); - extent += btVector3(getMargin(),getMargin(),getMargin()); + aabbMin = center - extent; aabbMax = center + extent; diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp index 9b78fc0f7c2..a248c55b571 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btOptimizedBvh.cpp @@ -306,6 +306,8 @@ void btOptimizedBvh::updateBvhNodes(btStridingMeshInterface* meshInterface,int f if (curNodeSubPart >= 0) meshInterface->unLockReadOnlyVertexBase(curNodeSubPart); meshInterface->getLockedReadOnlyVertexIndexBase(&vertexbase,numverts, type,stride,&indexbase,indexstride,numfaces,indicestype,nodeSubPart); + + curNodeSubPart = nodeSubPart; btAssert(indicestype==PHY_INTEGER||indicestype==PHY_SHORT); } //triangles->getLockedReadOnlyVertexIndexBase(vertexBase,numVerts, diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h index 0d55e4fe92c..4c4ce7feaa7 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btPolyhedralConvexShape.h @@ -18,6 +18,7 @@ subject to the following restrictions: #include "LinearMath/btPoint3.h" #include "LinearMath/btMatrix3x3.h" +#include "LinearMath/btAabbUtil2.h" #include "btConvexInternalShape.h" @@ -46,28 +47,7 @@ public: //lazy evaluation of local aabb btAssert(m_isLocalAabbValid); - - btAssert(m_localAabbMin.getX() <= m_localAabbMax.getX()); - btAssert(m_localAabbMin.getY() <= m_localAabbMax.getY()); - btAssert(m_localAabbMin.getZ() <= m_localAabbMax.getZ()); - - - btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); - btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); - - btMatrix3x3 abs_b = trans.getBasis().absolute(); - - btPoint3 center = trans(localCenter); - - btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), - abs_b[1].dot(localHalfExtents), - abs_b[2].dot(localHalfExtents)); - extent += btVector3(margin,margin,margin); - - aabbMin = center - extent; - aabbMax = center + extent; - - + btTransformAabb(m_localAabbMin,m_localAabbMax,margin,trans,aabbMin,aabbMax); } diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp new file mode 100644 index 00000000000..5a17b4e2df0 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.cpp @@ -0,0 +1,103 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 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 "btScaledBvhTriangleMeshShape.h" + +btScaledBvhTriangleMeshShape::btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,btVector3 localScaling) +:m_bvhTriMeshShape(childShape), +m_localScaling(localScaling) +{ + +} + +btScaledBvhTriangleMeshShape::~btScaledBvhTriangleMeshShape() +{ +} + + +class btScaledTriangleCallback : public btTriangleCallback +{ + btTriangleCallback* m_originalCallback; + + btVector3 m_localScaling; + +public: + + btScaledTriangleCallback(btTriangleCallback* originalCallback,btVector3 localScaling) + :m_originalCallback(originalCallback), + m_localScaling(localScaling) + { + } + + virtual void processTriangle(btVector3* triangle, int partId, int triangleIndex) + { + btVector3 newTriangle[3]; + newTriangle[0] = triangle[0]*m_localScaling; + newTriangle[1] = triangle[1]*m_localScaling; + newTriangle[2] = triangle[2]*m_localScaling; + m_originalCallback->processTriangle(&newTriangle[0],partId,triangleIndex); + } +}; + +void btScaledBvhTriangleMeshShape::processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const +{ + btScaledTriangleCallback scaledCallback(callback,m_localScaling); + + btVector3 invLocalScaling(1.f/m_localScaling.getX(),1.f/m_localScaling.getY(),1.f/m_localScaling.getZ()); + btVector3 scaledAabbMin = aabbMin * invLocalScaling; + btVector3 scaledAabbMax = aabbMax * invLocalScaling; + m_bvhTriMeshShape->processAllTriangles(&scaledCallback,scaledAabbMin,scaledAabbMax); +} + + +void btScaledBvhTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,btVector3& aabbMax) const +{ + btVector3 localAabbMin = m_bvhTriMeshShape->getLocalAabbMin(); + btVector3 localAabbMax = m_bvhTriMeshShape->getLocalAabbMax(); + localAabbMin *= m_localScaling; + localAabbMax *= m_localScaling; + + btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin); + btScalar margin = m_bvhTriMeshShape->getMargin(); + localHalfExtents += btVector3(margin,margin,margin); + btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin); + + btMatrix3x3 abs_b = trans.getBasis().absolute(); + + btPoint3 center = trans(localCenter); + + btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + aabbMin = center - extent; + aabbMax = center + extent; + +} + +void btScaledBvhTriangleMeshShape::setLocalScaling(const btVector3& scaling) +{ + m_localScaling = scaling; +} + +const btVector3& btScaledBvhTriangleMeshShape::getLocalScaling() const +{ + return m_localScaling; +} + +void btScaledBvhTriangleMeshShape::calculateLocalInertia(btScalar mass,btVector3& inertia) const +{ + ///don't make this a movable object! + btAssert(0); +} diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h new file mode 100644 index 00000000000..8e1d29fc005 --- /dev/null +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h @@ -0,0 +1,57 @@ +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 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. +*/ + +#ifndef SCALED_BVH_TRIANGLE_MESH_SHAPE_H +#define SCALED_BVH_TRIANGLE_MESH_SHAPE_H + +#include "BulletCollision/CollisionShapes/btBvhTriangleMeshShape.h" + + +///The btScaledBvhTriangleMeshShape allows to instance a scaled version of an existing btBvhTriangleMeshShape. +///Note that each btBvhTriangleMeshShape still can have its own local scaling, independent from this btScaledBvhTriangleMeshShape 'localScaling' +ATTRIBUTE_ALIGNED16(class) btScaledBvhTriangleMeshShape : public btConcaveShape +{ + + + btVector3 m_localScaling; + + btBvhTriangleMeshShape* m_bvhTriMeshShape; + +public: + + + btScaledBvhTriangleMeshShape(btBvhTriangleMeshShape* childShape,btVector3 localScaling); + + virtual ~btScaledBvhTriangleMeshShape(); + + 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; + } + + virtual void getAabb(const btTransform& t,btVector3& aabbMin,btVector3& aabbMax) const; + virtual void setLocalScaling(const btVector3& scaling); + virtual const btVector3& getLocalScaling() const; + virtual void calculateLocalInertia(btScalar mass,btVector3& inertia) const; + + virtual void processAllTriangles(btTriangleCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const; + + //debugging + virtual const char* getName()const {return "SCALEDBVHTRIANGLEMESH";} + +}; + +#endif //BVH_TRIANGLE_MESH_SHAPE_H diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp index cd0a00bbd6f..0a2c77096d1 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.cpp @@ -47,6 +47,7 @@ void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,bt { btVector3 localHalfExtents = btScalar(0.5)*(m_localAabbMax-m_localAabbMin); + localHalfExtents += btVector3(getMargin(),getMargin(),getMargin()); btVector3 localCenter = btScalar(0.5)*(m_localAabbMax+m_localAabbMin); btMatrix3x3 abs_b = trans.getBasis().absolute(); @@ -56,12 +57,10 @@ void btTriangleMeshShape::getAabb(const btTransform& trans,btVector3& aabbMin,bt btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), abs_b[1].dot(localHalfExtents), abs_b[2].dot(localHalfExtents)); - extent += btVector3(getMargin(),getMargin(),getMargin()); - aabbMin = center - extent; aabbMax = center + extent; - + } void btTriangleMeshShape::recalcLocalAabb() diff --git a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h index 9fba77cb547..c9eabafe290 100644 --- a/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h +++ b/extern/bullet2/src/BulletCollision/CollisionShapes/btTriangleMeshShape.h @@ -65,6 +65,16 @@ public: return m_meshInterface; } + const btVector3& getLocalAabbMin() const + { + return m_localAabbMin; + } + const btVector3& getLocalAabbMax() const + { + return m_localAabbMax; + } + + //debugging virtual const char* getName()const {return "TRIANGLEMESH";} diff --git a/extern/bullet2/src/BulletDynamics/CMakeLists.txt b/extern/bullet2/src/BulletDynamics/CMakeLists.txt index 8598575799a..58b023e9775 100644 --- a/extern/bullet2/src/BulletDynamics/CMakeLists.txt +++ b/extern/bullet2/src/BulletDynamics/CMakeLists.txt @@ -5,16 +5,32 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src } ADD_LIBRARY(LibBulletDynamics ConstraintSolver/btContactConstraint.cpp + ConstraintSolver/btContactConstraint.h + ConstraintSolver/btConeTwistConstraint.cpp + ConstraintSolver/btConeTwistConstraint.h ConstraintSolver/btGeneric6DofConstraint.cpp + ConstraintSolver/btGeneric6DofConstraint.h ConstraintSolver/btHingeConstraint.cpp + ConstraintSolver/btHingeConstraint.h ConstraintSolver/btPoint2PointConstraint.cpp + ConstraintSolver/btPoint2PointConstraint.h ConstraintSolver/btSequentialImpulseConstraintSolver.cpp + ConstraintSolver/btSequentialImpulseConstraintSolver.h + ConstraintSolver/btSliderConstraint.cpp + ConstraintSolver/btSliderConstraint.h ConstraintSolver/btSolve2LinearConstraint.cpp + ConstraintSolver/btSolve2LinearConstraint.h ConstraintSolver/btTypedConstraint.cpp - Dynamics/btDiscreteDynamicsWorld.cpp - Dynamics/btSimpleDynamicsWorld.cpp + ConstraintSolver/btTypedConstraint.h Dynamics/Bullet-C-API.cpp + Dynamics/btDiscreteDynamicsWorld.cpp + Dynamics/btDiscreteDynamicsWorld.h + Dynamics/btSimpleDynamicsWorld.cpp + Dynamics/btSimpleDynamicsWorld.h Dynamics/btRigidBody.cpp + Dynamics/btRigidBody.h Vehicle/btRaycastVehicle.cpp + Vehicle/btRaycastVehicle.h Vehicle/btWheelInfo.cpp + Vehicle/btWheelInfo.h ) diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp index e11b49d9420..61dad522a5b 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btConeTwistConstraint.cpp @@ -114,17 +114,34 @@ void btConeTwistConstraint::buildJacobian() btScalar swing1=btScalar(0.),swing2 = btScalar(0.); + btScalar swx=btScalar(0.),swy = btScalar(0.); + btScalar thresh = btScalar(10.); + btScalar fact; + // Get Frame into world space if (m_swingSpan1 >= btScalar(0.05f)) { b1Axis2 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(1); - swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) ); +// swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) ); + swx = b2Axis1.dot(b1Axis1); + swy = b2Axis1.dot(b1Axis2); + swing1 = btAtan2Fast(swy, swx); + fact = (swy*swy + swx*swx) * thresh * thresh; + fact = fact / (fact + btScalar(1.0)); + swing1 *= fact; + } if (m_swingSpan2 >= btScalar(0.05f)) { b1Axis3 = getRigidBodyA().getCenterOfMassTransform().getBasis() * this->m_rbAFrame.getBasis().getColumn(2); - swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) ); +// swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) ); + swx = b2Axis1.dot(b1Axis1); + swy = b2Axis1.dot(b1Axis3); + swing2 = btAtan2Fast(swy, swx); + fact = (swy*swy + swx*swx) * thresh * thresh; + fact = fact / (fact + btScalar(1.0)); + swing2 *= fact; } btScalar RMaxAngle1Sq = 1.0f / (m_swingSpan1*m_swingSpan1); diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp index 114abce24c7..a0523a8c76b 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btHingeConstraint.cpp @@ -241,15 +241,18 @@ void btHingeConstraint::buildJacobian() m_solveLimit = false; m_accLimitImpulse = btScalar(0.); - if (m_lowerLimit < m_upperLimit) +// if (m_lowerLimit < m_upperLimit) + if (m_lowerLimit <= m_upperLimit) { - if (hingeAngle <= m_lowerLimit*m_limitSoftness) +// if (hingeAngle <= m_lowerLimit*m_limitSoftness) + if (hingeAngle <= m_lowerLimit) { m_correction = (m_lowerLimit - hingeAngle); m_limitSign = 1.0f; m_solveLimit = true; } - else if (hingeAngle >= m_upperLimit*m_limitSoftness) +// else if (hingeAngle >= m_upperLimit*m_limitSoftness) + else if (hingeAngle >= m_upperLimit) { m_correction = m_upperLimit - hingeAngle; m_limitSign = -1.0f; diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeContactJoint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeContactJoint.cpp deleted file mode 100644 index 7d2f19998ac..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeContactJoint.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/* -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 "btOdeContactJoint.h" -#include "btOdeSolverBody.h" -#include "BulletCollision/NarrowPhaseCollision/btPersistentManifold.h" - - -//this constant needs to be set up so different solvers give 'similar' results -#define FRICTION_CONSTANT 120.f - - -btOdeContactJoint::btOdeContactJoint(btPersistentManifold* manifold,int index,bool swap,btOdeSolverBody* body0,btOdeSolverBody* body1) -:m_manifold(manifold), -m_index(index), -m_swapBodies(swap), -m_body0(body0), -m_body1(body1) -{ -} - -int m_numRows = 3; - - -void btOdeContactJoint::GetInfo1(Info1 *info) -{ - info->m = m_numRows; - //friction adds another 2... - - info->nub = 0; -} - -#define dCROSS(a,op,b,c) \ - (a)[0] op ((b)[1]*(c)[2] - (b)[2]*(c)[1]); \ - (a)[1] op ((b)[2]*(c)[0] - (b)[0]*(c)[2]); \ - (a)[2] op ((b)[0]*(c)[1] - (b)[1]*(c)[0]); - -#define M_SQRT12 btScalar(0.7071067811865475244008443621048490) - -#define dRecipSqrt(x) ((float)(1.0f/btSqrt(float(x)))) /* reciprocal square root */ - - - -void dPlaneSpace1 (const dVector3 n, dVector3 p, dVector3 q); -void dPlaneSpace1 (const dVector3 n, dVector3 p, dVector3 q) -{ - if (btFabs(n[2]) > M_SQRT12) { - // choose p in y-z plane - btScalar a = n[1]*n[1] + n[2]*n[2]; - btScalar k = dRecipSqrt (a); - p[0] = 0; - p[1] = -n[2]*k; - p[2] = n[1]*k; - // set q = n x p - q[0] = a*k; - q[1] = -n[0]*p[2]; - q[2] = n[0]*p[1]; - } - else { - // choose p in x-y plane - btScalar a = n[0]*n[0] + n[1]*n[1]; - btScalar k = dRecipSqrt (a); - p[0] = -n[1]*k; - p[1] = n[0]*k; - p[2] = 0; - // set q = n x p - q[0] = -n[2]*p[1]; - q[1] = n[2]*p[0]; - q[2] = a*k; - } -} - - - -void btOdeContactJoint::GetInfo2(Info2 *info) -{ - - int s = info->rowskip; - int s2 = 2*s; - - float swapFactor = m_swapBodies ? -1.f : 1.f; - - // get normal, with sign adjusted for body1/body2 polarity - dVector3 normal; - - - btManifoldPoint& point = m_manifold->getContactPoint(m_index); - - normal[0] = swapFactor*point.m_normalWorldOnB.x(); - normal[1] = swapFactor*point.m_normalWorldOnB.y(); - normal[2] = swapFactor*point.m_normalWorldOnB.z(); - normal[3] = 0; // @@@ hmmm - - assert(m_body0); - // if (GetBody0()) - btVector3 relativePositionA; - { - relativePositionA = point.getPositionWorldOnA() - m_body0->m_centerOfMassPosition; - dVector3 c1; - c1[0] = relativePositionA.x(); - c1[1] = relativePositionA.y(); - c1[2] = relativePositionA.z(); - - // set jacobian for normal - info->J1l[0] = normal[0]; - info->J1l[1] = normal[1]; - info->J1l[2] = normal[2]; - dCROSS (info->J1a,=,c1,normal); - - } - - btVector3 relativePositionB(0,0,0); - if (m_body1) - { - // if (GetBody1()) - - { - dVector3 c2; - btVector3 posBody1 = m_body1 ? m_body1->m_centerOfMassPosition : btVector3(0,0,0); - relativePositionB = point.getPositionWorldOnB() - posBody1; - - // for (i=0; i<3; i++) c2[i] = j->contact.geom.pos[i] - - // j->node[1].body->pos[i]; - c2[0] = relativePositionB.x(); - c2[1] = relativePositionB.y(); - c2[2] = relativePositionB.z(); - - info->J2l[0] = -normal[0]; - info->J2l[1] = -normal[1]; - info->J2l[2] = -normal[2]; - dCROSS (info->J2a,= -,c2,normal); - } - } - - btScalar k = info->fps * info->erp; - - float depth = -point.getDistance(); -// if (depth < 0.f) -// depth = 0.f; - - info->c[0] = k * depth; - //float maxvel = .2f; - -// if (info->c[0] > maxvel) -// info->c[0] = maxvel; - - - //can override it, not necessary -// info->cfm[0] = 0.f; -// info->cfm[1] = 0.f; -// info->cfm[2] = 0.f; - - - - // set LCP limits for normal - info->lo[0] = 0; - info->hi[0] = 1e30f;//dInfinity; - info->lo[1] = 0; - info->hi[1] = 0.f; - info->lo[2] = 0.f; - info->hi[2] = 0.f; - -#define DO_THE_FRICTION_2 -#ifdef DO_THE_FRICTION_2 - // now do jacobian for tangential forces - dVector3 t1,t2; // two vectors tangential to normal - - dVector3 c1; - c1[0] = relativePositionA.x(); - c1[1] = relativePositionA.y(); - c1[2] = relativePositionA.z(); - - dVector3 c2; - c2[0] = relativePositionB.x(); - c2[1] = relativePositionB.y(); - c2[2] = relativePositionB.z(); - - //combined friction is available in the contact point - float friction = 0.25;//FRICTION_CONSTANT ;//* m_body0->m_friction * m_body1->m_friction; - - // first friction direction - if (m_numRows >= 2) - { - - - - dPlaneSpace1 (normal,t1,t2); - - info->J1l[s+0] = t1[0]; - info->J1l[s+1] = t1[1]; - info->J1l[s+2] = t1[2]; - dCROSS (info->J1a+s,=,c1,t1); -// if (1) { //j->node[1].body) { - info->J2l[s+0] = -t1[0]; - info->J2l[s+1] = -t1[1]; - info->J2l[s+2] = -t1[2]; - dCROSS (info->J2a+s,= -,c2,t1); -// } - // set right hand side -// if (0) {//j->contact.surface.mode & dContactMotion1) { - //info->c[1] = j->contact.surface.motion1; -// } - // set LCP bounds and friction index. this depends on the approximation - // mode - //1e30f - - - info->lo[1] = -friction;//-j->contact.surface.mu; - info->hi[1] = friction;//j->contact.surface.mu; -// if (1)//j->contact.surface.mode & dContactApprox1_1) - info->findex[1] = 0; - - // set slip (constraint force mixing) -// if (0)//j->contact.surface.mode & dContactSlip1) -// { -// // info->cfm[1] = j->contact.surface.slip1; -// } else -// { -// //info->cfm[1] = 0.f; -// } - } - - // second friction direction - if (m_numRows >= 3) { - info->J1l[s2+0] = t2[0]; - info->J1l[s2+1] = t2[1]; - info->J1l[s2+2] = t2[2]; - dCROSS (info->J1a+s2,=,c1,t2); -// if (1) { //j->node[1].body) { - info->J2l[s2+0] = -t2[0]; - info->J2l[s2+1] = -t2[1]; - info->J2l[s2+2] = -t2[2]; - dCROSS (info->J2a+s2,= -,c2,t2); -// } - - // set right hand side -// if (0){//j->contact.surface.mode & dContactMotion2) { - //info->c[2] = j->contact.surface.motion2; -// } - // set LCP bounds and friction index. this depends on the approximation - // mode -// if (0){//j->contact.surface.mode & dContactMu2) { - //info->lo[2] = -j->contact.surface.mu2; - //info->hi[2] = j->contact.surface.mu2; -// } -// else { - info->lo[2] = -friction; - info->hi[2] = friction; -// } -// if (0)//j->contact.surface.mode & dContactApprox1_2) - -// { -// info->findex[2] = 0; -// } - // set slip (constraint force mixing) -// if (0) //j->contact.surface.mode & dContactSlip2) - -// { - //info->cfm[2] = j->contact.surface.slip2; - -// } - } - -#endif //DO_THE_FRICTION_2 - -} - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeContactJoint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeContactJoint.h deleted file mode 100644 index 8dd0282c59e..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeContactJoint.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -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. -*/ - -#ifndef CONTACT_JOINT_H -#define CONTACT_JOINT_H - -#include "btOdeJoint.h" -struct btOdeSolverBody; -class btPersistentManifold; - -class btOdeContactJoint : public btOdeJoint -{ - btPersistentManifold* m_manifold; - int m_index; - bool m_swapBodies; - btOdeSolverBody* m_body0; - btOdeSolverBody* m_body1; - - -public: - - btOdeContactJoint() {}; - - btOdeContactJoint(btPersistentManifold* manifold,int index,bool swap,btOdeSolverBody* body0,btOdeSolverBody* body1); - - //btOdeJoint interface for solver - - virtual void GetInfo1(Info1 *info); - - virtual void GetInfo2(Info2 *info); - - - - -}; - -#endif //CONTACT_JOINT_H - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeJoint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeJoint.cpp deleted file mode 100644 index 46c3783c6a0..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeJoint.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* -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 "btOdeJoint.h" - -btOdeJoint::btOdeJoint() -{ - -} -btOdeJoint::~btOdeJoint() -{ - -} diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeJoint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeJoint.h deleted file mode 100644 index 50733d1418f..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeJoint.h +++ /dev/null @@ -1,94 +0,0 @@ -/* -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. -*/ - -#ifndef btOdeJoint_H -#define btOdeJoint_H - -struct btOdeSolverBody; -class btOdeJoint; - -#include "LinearMath/btScalar.h" - -struct BU_ContactJointNode { - btOdeJoint *joint; // pointer to enclosing btOdeJoint object - btOdeSolverBody* body; // *other* body this joint is connected to -}; -typedef btScalar dVector3[4]; - - -class btOdeJoint { - -public: - // naming convention: the "first" body this is connected to is node[0].body, - // and the "second" body is node[1].body. if this joint is only connected - // to one body then the second body is 0. - - // info returned by getInfo1 function. the constraint dimension is m (<=6). - // i.e. that is the total number of rows in the jacobian. `nub' is the - // number of unbounded variables (which have lo,hi = -/+ infinity). - - btOdeJoint(); - virtual ~btOdeJoint(); - - - struct Info1 { - int m,nub; - }; - - // info returned by getInfo2 function - - struct Info2 { - // integrator parameters: frames per second (1/stepsize), default error - // reduction parameter (0..1). - btScalar fps,erp; - - // for the first and second body, pointers to two (linear and angular) - // n*3 jacobian sub matrices, stored by rows. these matrices will have - // been initialized to 0 on entry. if the second body is zero then the - // J2xx pointers may be 0. - btScalar *J1l,*J1a,*J2l,*J2a; - - // elements to jump from one row to the next in J's - int rowskip; - - // right hand sides of the equation J*v = c + cfm * lambda. cfm is the - // "constraint force mixing" vector. c is set to zero on entry, cfm is - // set to a constant value (typically very small or zero) value on entry. - btScalar *c,*cfm; - - // lo and hi limits for variables (set to -/+ infinity on entry). - btScalar *lo,*hi; - - // findex vector for variables. see the LCP solver interface for a - // description of what this does. this is set to -1 on entry. - // note that the returned indexes are relative to the first index of - // the constraint. - int *findex; - }; - - // virtual function table: size of the joint structure, function pointers. - // we do it this way instead of using C++ virtual functions because - // sometimes we need to allocate joints ourself within a memory pool. - - virtual void GetInfo1 (Info1 *info)=0; - virtual void GetInfo2 (Info2 *info)=0; - - int flags; // dJOINT_xxx flags - BU_ContactJointNode node[2]; // connections to bodies. node[1].body can be 0 - btScalar lambda[6]; // lambda generated by last step -}; - - -#endif //btOdeJoint_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeMacros.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeMacros.h deleted file mode 100644 index e4bc2628bd4..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeMacros.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Quickstep constraint solver re-distributed under the ZLib license with permission from Russell L. Smith - * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. - * All rights reserved. Email: russ@q12.org Web: www.q12.org - Bullet Continuous Collision Detection and Physics Library - Bullet is 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. -*/ - -#define ODE_MACROS -#ifdef ODE_MACROS - -#include "LinearMath/btScalar.h" - -typedef btScalar dVector4[4]; -typedef btScalar dMatrix3[4*3]; -#define dInfinity FLT_MAX - - - -#define dRecip(x) ((float)(1.0f/(x))) /* reciprocal */ - - - -#define dMULTIPLY0_331NEW(A,op,B,C) \ -{\ - btScalar tmp[3];\ - tmp[0] = C.getX();\ - tmp[1] = C.getY();\ - tmp[2] = C.getZ();\ - dMULTIPLYOP0_331(A,op,B,tmp);\ -} - -#define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C) -#define dMULTIPLYOP0_331(A,op,B,C) \ - (A)[0] op dDOT1((B),(C)); \ - (A)[1] op dDOT1((B+4),(C)); \ - (A)[2] op dDOT1((B+8),(C)); - -#define dAASSERT btAssert -#define dIASSERT btAssert - -#define REAL float -#define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)]) -inline btScalar dDOT1 (const btScalar *a, const btScalar *b) -{ return dDOTpq(a,b,1,1); } -#define dDOT14(a,b) dDOTpq(a,b,1,4) - -#define dCROSS(a,op,b,c) \ - (a)[0] op ((b)[1]*(c)[2] - (b)[2]*(c)[1]); \ - (a)[1] op ((b)[2]*(c)[0] - (b)[0]*(c)[2]); \ - (a)[2] op ((b)[0]*(c)[1] - (b)[1]*(c)[0]); - -/* - * set a 3x3 submatrix of A to a matrix such that submatrix(A)*b = a x b. - * A is stored by rows, and has `skip' elements per row. the matrix is - * assumed to be already zero, so this does not write zero elements! - * if (plus,minus) is (+,-) then a positive version will be written. - * if (plus,minus) is (-,+) then a negative version will be written. - */ - -#define dCROSSMAT(A,a,skip,plus,minus) \ -{ \ - (A)[1] = minus (a)[2]; \ - (A)[2] = plus (a)[1]; \ - (A)[(skip)+0] = plus (a)[2]; \ - (A)[(skip)+2] = minus (a)[0]; \ - (A)[2*(skip)+0] = minus (a)[1]; \ - (A)[2*(skip)+1] = plus (a)[0]; \ -} - - -#define dMULTIPLYOP2_333(A,op,B,C) \ - (A)[0] op dDOT1((B),(C)); \ - (A)[1] op dDOT1((B),(C+4)); \ - (A)[2] op dDOT1((B),(C+8)); \ - (A)[4] op dDOT1((B+4),(C)); \ - (A)[5] op dDOT1((B+4),(C+4)); \ - (A)[6] op dDOT1((B+4),(C+8)); \ - (A)[8] op dDOT1((B+8),(C)); \ - (A)[9] op dDOT1((B+8),(C+4)); \ - (A)[10] op dDOT1((B+8),(C+8)); - -#define dMULTIPLYOP0_333(A,op,B,C) \ - (A)[0] op dDOT14((B),(C)); \ - (A)[1] op dDOT14((B),(C+1)); \ - (A)[2] op dDOT14((B),(C+2)); \ - (A)[4] op dDOT14((B+4),(C)); \ - (A)[5] op dDOT14((B+4),(C+1)); \ - (A)[6] op dDOT14((B+4),(C+2)); \ - (A)[8] op dDOT14((B+8),(C)); \ - (A)[9] op dDOT14((B+8),(C+1)); \ - (A)[10] op dDOT14((B+8),(C+2)); - -#define dMULTIPLY2_333(A,B,C) dMULTIPLYOP2_333(A,=,B,C) -#define dMULTIPLY0_333(A,B,C) dMULTIPLYOP0_333(A,=,B,C) -#define dMULTIPLYADD0_331(A,B,C) dMULTIPLYOP0_331(A,+=,B,C) - - -//////////////////////////////////////////////////////////////////// -#define EFFICIENT_ALIGNMENT 16 -#define dEFFICIENT_SIZE(x) ((((x)-1)|(EFFICIENT_ALIGNMENT-1))+1) -/* alloca aligned to the EFFICIENT_ALIGNMENT. note that this can waste - * up to 15 bytes per allocation, depending on what alloca() returns. - */ - -#define dALLOCA16(n) \ - ((char*)dEFFICIENT_SIZE(((size_t)(alloca((n)+(EFFICIENT_ALIGNMENT-1)))))) - -//#define ALLOCA dALLOCA16 - -typedef const btScalar *dRealPtr; -typedef btScalar *dRealMutablePtr; -//#define dRealArray(name,n) btScalar name[n]; -//#define dRealAllocaArray(name,n) btScalar *name = (btScalar*) ALLOCA ((n)*sizeof(btScalar)); - -/////////////////////////////////////////////////////////////////////////////// - - //Remotion: 10.10.2007 -#define ALLOCA(size) stackAlloc->allocate( dEFFICIENT_SIZE(size) ); - -//#define dRealAllocaArray(name,size) btScalar *name = (btScalar*) stackAlloc->allocate(dEFFICIENT_SIZE(size)*sizeof(btScalar)); -#define dRealAllocaArray(name,size) btScalar *name = NULL; \ - unsigned int memNeeded_##name = dEFFICIENT_SIZE(size)*sizeof(btScalar); \ - if (memNeeded_##name < static_cast(stackAlloc->getAvailableMemory())) name = (btScalar*) stackAlloc->allocate(memNeeded_##name); \ - else{ btAssert(memNeeded_##name < static_cast(stackAlloc->getAvailableMemory())); name = (btScalar*) alloca(memNeeded_##name); } - - - - - -/////////////////////////////////////////////////////////////////////////////// -#if 0 -inline void dSetZero1 (btScalar *a, int n) -{ - dAASSERT (a && n >= 0); - while (n > 0) { - *(a++) = 0; - n--; - } -} - -inline void dSetValue1 (btScalar *a, int n, btScalar value) -{ - dAASSERT (a && n >= 0); - while (n > 0) { - *(a++) = value; - n--; - } -} -#else - -/// This macros are for MSVC and XCode compilers. Remotion. - - -#include //for memset - -//Remotion: 10.10.2007 -//------------------------------------------------------------------------------ -#define IS_ALIGNED_16(x) ((size_t(x)&15)==0) -//------------------------------------------------------------------------------ -inline void dSetZero1 (btScalar *dest, int size) -{ - dAASSERT (dest && size >= 0); - memset(dest, 0, size * sizeof(btScalar)); -} -//------------------------------------------------------------------------------ -inline void dSetValue1 (btScalar *dest, int size, btScalar val) -{ - dAASSERT (dest && size >= 0); - int n_mod4 = size & 3; - int n4 = size - n_mod4; -/*#ifdef __USE_SSE__ -//it is not supported on double precision, todo... - if(IS_ALIGNED_16(dest)){ - __m128 xmm0 = _mm_set_ps1(val); - for (int i=0; i -#include "LinearMath/btQuickprof.h" - -#include "LinearMath/btIDebugDraw.h" - -#define USE_SOR_SOLVER - -#include "btSorLcp.h" - -#include -#include //FLT_MAX -#ifdef WIN32 -#include -#endif -#include -#include - -#if defined (WIN32) -#include -#else -#if defined (__FreeBSD__) -#include -#else -#include -#endif -#endif - -class btOdeJoint; - -//see below -//to bridge with ODE quickstep, we make a temp copy of the rigidbodies in each simultion island - - -btOdeQuickstepConstraintSolver::btOdeQuickstepConstraintSolver(): - m_cfm(0.f),//1e-5f), - m_erp(0.4f) -{ -} - - -//iterative lcp and penalty method -btScalar btOdeQuickstepConstraintSolver::solveGroup(btCollisionObject** /*bodies*/,int numBulletBodies,btPersistentManifold** manifoldPtr, int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& infoGlobal,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc,btDispatcher* /*dispatcher*/) -{ - - m_CurBody = 0; - m_CurJoint = 0; - m_CurTypedJoint = 0; - int j; - - int max_contacts = 0; /// should be 4 //Remotion - for ( j=0;jgetNumContacts() > max_contacts) max_contacts = manifold->getNumContacts(); - } - //if(max_contacts > 4) - // printf(" max_contacts > 4"); - - int numBodies = 0; - m_odeBodies.clear(); - m_odeBodies.reserve(numBulletBodies + 1); //??? - // btOdeSolverBody* odeBodies [ODE_MAX_SOLVER_BODIES]; - - int numJoints = 0; - m_joints.clear(); - m_joints.reserve(numManifolds * max_contacts + 4 + numConstraints + 1); //??? - // btOdeJoint* joints [ODE_MAX_SOLVER_JOINTS*2]; - - m_SolverBodyArray.resize(numBulletBodies + 1); - m_JointArray.resize(numManifolds * max_contacts + 4); - m_TypedJointArray.resize(numConstraints + 1); - - - //capture contacts - int body0=-1,body1=-1; - for (j=0;jgetNumContacts() > 0) - { - body0 = ConvertBody((btRigidBody*)manifold->getBody0(),m_odeBodies,numBodies); - body1 = ConvertBody((btRigidBody*)manifold->getBody1(),m_odeBodies,numBodies); - ConvertConstraint(manifold,m_joints,numJoints,m_odeBodies,body0,body1,debugDrawer); - } - } - - //capture constraints - for (j=0;jgetRigidBodyA(),m_odeBodies,numBodies); - body1 = ConvertBody((btRigidBody*)&typedconstraint->getRigidBodyB(),m_odeBodies,numBodies); - ConvertTypedConstraint(typedconstraint,m_joints,numJoints,m_odeBodies,body0,body1,debugDrawer); - } - //if(numBodies > numBulletBodies) - // printf(" numBodies > numBulletBodies"); - //if(numJoints > numManifolds * 4 + numConstraints) - // printf(" numJoints > numManifolds * 4 + numConstraints"); - - - m_SorLcpSolver.SolveInternal1(m_cfm,m_erp,m_odeBodies,numBodies,m_joints,numJoints,infoGlobal,stackAlloc); ///do - - //write back resulting velocities - for (int i=0;im_invMass) - { - m_odeBodies[i]->m_originalBody->setLinearVelocity(m_odeBodies[i]->m_linearVelocity); - m_odeBodies[i]->m_originalBody->setAngularVelocity(m_odeBodies[i]->m_angularVelocity); - } - } - - - /// Remotion, just free all this here - m_odeBodies.clear(); - m_joints.clear(); - - m_SolverBodyArray.clear(); - m_JointArray.clear(); - m_TypedJointArray.clear(); - - return 0.f; - -} - -///////////////////////////////////////////////////////////////////////////////// - - -typedef btScalar dQuaternion[4]; -#define _R(i,j) R[(i)*4+(j)] - -void dRfromQ1 (dMatrix3 R, const dQuaternion q); -void dRfromQ1 (dMatrix3 R, const dQuaternion q) -{ - // q = (s,vx,vy,vz) - btScalar qq1 = 2.f*q[1]*q[1]; - btScalar qq2 = 2.f*q[2]*q[2]; - btScalar qq3 = 2.f*q[3]*q[3]; - _R(0,0) = 1.f - qq2 - qq3; - _R(0,1) = 2*(q[1]*q[2] - q[0]*q[3]); - _R(0,2) = 2*(q[1]*q[3] + q[0]*q[2]); - _R(0,3) = 0.f; - - _R(1,0) = 2*(q[1]*q[2] + q[0]*q[3]); - _R(1,1) = 1.f - qq1 - qq3; - _R(1,2) = 2*(q[2]*q[3] - q[0]*q[1]); - _R(1,3) = 0.f; - - _R(2,0) = 2*(q[1]*q[3] - q[0]*q[2]); - _R(2,1) = 2*(q[2]*q[3] + q[0]*q[1]); - _R(2,2) = 1.f - qq1 - qq2; - _R(2,3) = 0.f; - -} - - - -//int btOdeQuickstepConstraintSolver::ConvertBody(btRigidBody* orgBody,btOdeSolverBody** bodies,int& numBodies) -int btOdeQuickstepConstraintSolver::ConvertBody(btRigidBody* orgBody,btAlignedObjectArray< btOdeSolverBody*> &bodies,int& numBodies) -{ - assert(orgBody); - if (!orgBody || (orgBody->getInvMass() == 0.f) ) - { - return -1; - } - - if (orgBody->getCompanionId()>=0) - { - return orgBody->getCompanionId(); - } - //first try to find - int i,j; - - //if not found, create a new body - // btOdeSolverBody* body = bodies[numBodies] = &gSolverBodyArray[numBodies]; - btOdeSolverBody* body = &m_SolverBodyArray[numBodies]; - bodies.push_back(body); // Remotion 10.10.07: - - orgBody->setCompanionId(numBodies); - - numBodies++; - - body->m_originalBody = orgBody; - - body->m_facc.setValue(0,0,0,0); - body->m_tacc.setValue(0,0,0,0); - - body->m_linearVelocity = orgBody->getLinearVelocity(); - body->m_angularVelocity = orgBody->getAngularVelocity(); - body->m_invMass = orgBody->getInvMass(); - body->m_centerOfMassPosition = orgBody->getCenterOfMassPosition(); - body->m_friction = orgBody->getFriction(); - - //are the indices the same ? - for (i=0;i<4;i++) - { - for ( j=0;j<3;j++) - { - body->m_invI[i+4*j] = 0.f; - body->m_I[i+4*j] = 0.f; - } - } - body->m_invI[0+4*0] = orgBody->getInvInertiaDiagLocal().x(); - body->m_invI[1+4*1] = orgBody->getInvInertiaDiagLocal().y(); - body->m_invI[2+4*2] = orgBody->getInvInertiaDiagLocal().z(); - - body->m_I[0+0*4] = 1.f/orgBody->getInvInertiaDiagLocal().x(); - body->m_I[1+1*4] = 1.f/orgBody->getInvInertiaDiagLocal().y(); - body->m_I[2+2*4] = 1.f/orgBody->getInvInertiaDiagLocal().z(); - - - - - dQuaternion q; - - q[1] = orgBody->getOrientation().x(); - q[2] = orgBody->getOrientation().y(); - q[3] = orgBody->getOrientation().z(); - q[0] = orgBody->getOrientation().w(); - - dRfromQ1(body->m_R,q); - - return numBodies-1; -} - - - - - - - - - -void btOdeQuickstepConstraintSolver::ConvertConstraint(btPersistentManifold* manifold, - btAlignedObjectArray &joints,int& numJoints, - const btAlignedObjectArray< btOdeSolverBody*> &bodies, - int _bodyId0,int _bodyId1,btIDebugDraw* debugDrawer) -{ - - - manifold->refreshContactPoints(((btRigidBody*)manifold->getBody0())->getCenterOfMassTransform(), - ((btRigidBody*)manifold->getBody1())->getCenterOfMassTransform()); - - int bodyId0 = _bodyId0,bodyId1 = _bodyId1; - - int i,numContacts = manifold->getNumContacts(); - - bool swapBodies = (bodyId0 < 0); - - - btOdeSolverBody* body0,*body1; - - if (swapBodies) - { - bodyId0 = _bodyId1; - bodyId1 = _bodyId0; - - body0 = bodyId0>=0 ? bodies[bodyId0] : 0;//(btRigidBody*)manifold->getBody1(); - body1 = bodyId1>=0 ? bodies[bodyId1] : 0;//(btRigidBody*)manifold->getBody0(); - - } - else - { - body0 = bodyId0>=0 ? bodies[bodyId0] : 0;//(btRigidBody*)manifold->getBody0(); - body1 = bodyId1>=0 ? bodies[bodyId1] : 0;//(btRigidBody*)manifold->getBody1(); - } - - assert(bodyId0 >= 0); - - btVector3 color(0,1,0); - for (i=0;igetContactPoint(i).getDistance() < 0.0f) - { - - btOdeContactJoint* cont = new (&m_JointArray[m_CurJoint++]) btOdeContactJoint( manifold ,i, swapBodies,body0,body1); - //btOdeContactJoint* cont = new (&gJointArray[m_CurJoint++]) btOdeContactJoint( manifold ,i, swapBodies,body0,body1); - - cont->node[0].joint = cont; - cont->node[0].body = bodyId0 >= 0 ? bodies[bodyId0] : 0; - - cont->node[1].joint = cont; - cont->node[1].body = bodyId1 >= 0 ? bodies[bodyId1] : 0; - - // joints[numJoints++] = cont; - joints.push_back(cont); // Remotion 10.10.07: - numJoints++; - - for (int i=0;i<6;i++) - cont->lambda[i] = 0.f; - - cont->flags = 0; - } - } - - //create a new contact constraint -} - -void btOdeQuickstepConstraintSolver::ConvertTypedConstraint( - btTypedConstraint * constraint, - btAlignedObjectArray &joints,int& numJoints, - const btAlignedObjectArray< btOdeSolverBody*> &bodies,int _bodyId0,int _bodyId1,btIDebugDraw* /*debugDrawer*/) -{ - - int bodyId0 = _bodyId0,bodyId1 = _bodyId1; - bool swapBodies = (bodyId0 < 0); - - - btOdeSolverBody* body0,*body1; - - if (swapBodies) - { - bodyId0 = _bodyId1; - bodyId1 = _bodyId0; - - body0 = bodyId0>=0 ? bodies[bodyId0] : 0;//(btRigidBody*)manifold->getBody1(); - body1 = bodyId1>=0 ? bodies[bodyId1] : 0;//(btRigidBody*)manifold->getBody0(); - - } - else - { - body0 = bodyId0>=0 ? bodies[bodyId0] : 0;//(btRigidBody*)manifold->getBody0(); - body1 = bodyId1>=0 ? bodies[bodyId1] : 0;//(btRigidBody*)manifold->getBody1(); - } - - assert(bodyId0 >= 0); - - - //assert (m_CurTypedJoint < ODE_MAX_SOLVER_JOINTS); - - - btOdeTypedJoint * cont = NULL; - - // Determine constraint type - int joint_type = constraint->getConstraintType(); - switch(joint_type) - { - case POINT2POINT_CONSTRAINT_TYPE: - case D6_CONSTRAINT_TYPE: - cont = new (&m_TypedJointArray[m_CurTypedJoint ++]) btOdeTypedJoint(constraint,0, swapBodies,body0,body1); - //cont = new (&gTypedJointArray[m_CurTypedJoint ++]) btOdeTypedJoint(constraint,0, swapBodies,body0,body1); - break; - - }; - - if(cont) - { - cont->node[0].joint = cont; - cont->node[0].body = bodyId0 >= 0 ? bodies[bodyId0] : 0; - - cont->node[1].joint = cont; - cont->node[1].body = bodyId1 >= 0 ? bodies[bodyId1] : 0; - - // joints[numJoints++] = cont; - joints.push_back(cont); // Remotion 10.10.07: - numJoints++; - - for (int i=0;i<6;i++) - cont->lambda[i] = 0.f; - - cont->flags = 0; - } - -} diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeQuickstepConstraintSolver.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeQuickstepConstraintSolver.h deleted file mode 100644 index e548ea6fc22..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeQuickstepConstraintSolver.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Quickstep constraint solver re-distributed under the ZLib license with permission from Russell L. Smith - * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. - * All rights reserved. Email: russ@q12.org Web: www.q12.org - Bullet Continuous Collision Detection and Physics Library - Bullet is 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. -*/ - -#ifndef ODE_CONSTRAINT_SOLVER_H -#define ODE_CONSTRAINT_SOLVER_H - -#include "BulletDynamics/ConstraintSolver/btConstraintSolver.h" - -#include "LinearMath/btAlignedObjectArray.h" -#include "btOdeContactJoint.h" -#include "btOdeTypedJoint.h" -#include "btOdeSolverBody.h" -#include "btSorLcp.h" - -class btRigidBody; -struct btOdeSolverBody; -class btOdeJoint; - -/// btOdeQuickstepConstraintSolver is one of the available solvers for Bullet dynamics framework -/// It uses an adapted version quickstep solver from the Open Dynamics Engine project -class btOdeQuickstepConstraintSolver : public btConstraintSolver -{ -private: - int m_CurBody; - int m_CurJoint; - int m_CurTypedJoint; - - float m_cfm; - float m_erp; - - btSorLcpSolver m_SorLcpSolver; - - btAlignedObjectArray m_odeBodies; - btAlignedObjectArray m_joints; - - btAlignedObjectArray m_SolverBodyArray; - btAlignedObjectArray m_JointArray; - btAlignedObjectArray m_TypedJointArray; - - -private: - int ConvertBody(btRigidBody* body,btAlignedObjectArray< btOdeSolverBody*> &bodies,int& numBodies); - void ConvertConstraint(btPersistentManifold* manifold, - btAlignedObjectArray &joints,int& numJoints, - const btAlignedObjectArray< btOdeSolverBody*> &bodies, - int _bodyId0,int _bodyId1,btIDebugDraw* debugDrawer); - - void ConvertTypedConstraint( - btTypedConstraint * constraint, - btAlignedObjectArray &joints,int& numJoints, - const btAlignedObjectArray< btOdeSolverBody*> &bodies,int _bodyId0,int _bodyId1,btIDebugDraw* debugDrawer); - - -public: - - btOdeQuickstepConstraintSolver(); - - virtual ~btOdeQuickstepConstraintSolver() {} - - virtual btScalar solveGroup(btCollisionObject** bodies,int numBodies,btPersistentManifold** manifold,int numManifolds,btTypedConstraint** constraints,int numConstraints,const btContactSolverInfo& info,btIDebugDraw* debugDrawer,btStackAlloc* stackAlloc,btDispatcher* dispatcher); - - ///setConstraintForceMixing, the cfm adds some positive value to the main diagonal - ///This can improve convergence (make matrix positive semidefinite), but it can make the simulation look more 'springy' - void setConstraintForceMixing(float cfm) { - m_cfm = cfm; - } - - ///setErrorReductionParamter sets the maximum amount of error reduction - ///which limits energy addition during penetration depth recovery - void setErrorReductionParamter(float erp) - { - m_erp = erp; - } - - ///clear internal cached data and reset random seed - void reset() - { - m_SorLcpSolver.dRand2_seed = 0; - } - - void setRandSeed(unsigned long seed) - { - m_SorLcpSolver.dRand2_seed = seed; - } - unsigned long getRandSeed() const - { - return m_SorLcpSolver.dRand2_seed; - } -}; - - - - -#endif //ODE_CONSTRAINT_SOLVER_H diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeSolverBody.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeSolverBody.h deleted file mode 100644 index 0c936971b79..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeSolverBody.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -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. -*/ - -#ifndef ODE_SOLVER_BODY_H -#define ODE_SOLVER_BODY_H - -class btRigidBody; -#include "LinearMath/btVector3.h" -typedef btScalar dMatrix3[4*3]; - -///ODE's quickstep needs just a subset of the rigidbody data in its own layout, so make a temp copy -struct btOdeSolverBody -{ - btRigidBody* m_originalBody; - - btVector3 m_centerOfMassPosition; - /// for ode solver-binding - dMatrix3 m_R;//temp - dMatrix3 m_I; - dMatrix3 m_invI; - - int m_odeTag; - float m_invMass; - float m_friction; - - btVector3 m_tacc;//temp - btVector3 m_facc; - - btVector3 m_linearVelocity; - btVector3 m_angularVelocity; - -}; - - -#endif //#ifndef ODE_SOLVER_BODY_H - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeTypedJoint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeTypedJoint.cpp deleted file mode 100644 index f683bf7d748..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeTypedJoint.cpp +++ /dev/null @@ -1,880 +0,0 @@ -/* -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 "btOdeTypedJoint.h" -#include "btOdeSolverBody.h" -#include "btOdeMacros.h" -#include - -void btOdeTypedJoint::GetInfo1(Info1 *info) -{ - int joint_type = m_constraint->getConstraintType(); - switch (joint_type) - { - case POINT2POINT_CONSTRAINT_TYPE: - { - OdeP2PJoint p2pjoint(m_constraint,m_index,m_swapBodies,m_body0,m_body1); - p2pjoint.GetInfo1(info); - } - break; - case D6_CONSTRAINT_TYPE: - { - OdeD6Joint d6joint(m_constraint,m_index,m_swapBodies,m_body0,m_body1); - d6joint.GetInfo1(info); - } - break; - case SLIDER_CONSTRAINT_TYPE: - { - OdeSliderJoint sliderjoint(m_constraint,m_index,m_swapBodies,m_body0,m_body1); - sliderjoint.GetInfo1(info); - } - break; - }; -} - -void btOdeTypedJoint::GetInfo2(Info2 *info) -{ - int joint_type = m_constraint->getConstraintType(); - switch (joint_type) - { - case POINT2POINT_CONSTRAINT_TYPE: - { - OdeP2PJoint p2pjoint(m_constraint,m_index,m_swapBodies,m_body0,m_body1); - p2pjoint.GetInfo2(info); - } - break; - case D6_CONSTRAINT_TYPE: - { - OdeD6Joint d6joint(m_constraint,m_index,m_swapBodies,m_body0,m_body1); - d6joint.GetInfo2(info); - } - break; - case SLIDER_CONSTRAINT_TYPE: - { - OdeSliderJoint sliderjoint(m_constraint,m_index,m_swapBodies,m_body0,m_body1); - sliderjoint.GetInfo2(info); - } - break; - }; -} - - -OdeP2PJoint::OdeP2PJoint( - btTypedConstraint * constraint, - int index,bool swap,btOdeSolverBody* body0,btOdeSolverBody* body1): - btOdeTypedJoint(constraint,index,swap,body0,body1) -{ -} - - -void OdeP2PJoint::GetInfo1(Info1 *info) -{ - info->m = 3; - info->nub = 3; -} - - -void OdeP2PJoint::GetInfo2(Info2 *info) -{ - - btPoint2PointConstraint * p2pconstraint = this->getP2PConstraint(); - - //retrieve matrices - btTransform body0_trans; - if (m_body0) - { - body0_trans = m_body0->m_originalBody->getCenterOfMassTransform(); - } -// btScalar body0_mat[12]; -// body0_mat[0] = body0_trans.getBasis()[0][0]; -// body0_mat[1] = body0_trans.getBasis()[0][1]; -// body0_mat[2] = body0_trans.getBasis()[0][2]; -// body0_mat[4] = body0_trans.getBasis()[1][0]; -// body0_mat[5] = body0_trans.getBasis()[1][1]; -// body0_mat[6] = body0_trans.getBasis()[1][2]; -// body0_mat[8] = body0_trans.getBasis()[2][0]; -// body0_mat[9] = body0_trans.getBasis()[2][1]; -// body0_mat[10] = body0_trans.getBasis()[2][2]; - - btTransform body1_trans; - - if (m_body1) - { - body1_trans = m_body1->m_originalBody->getCenterOfMassTransform(); - } -// btScalar body1_mat[12]; -// body1_mat[0] = body1_trans.getBasis()[0][0]; -// body1_mat[1] = body1_trans.getBasis()[0][1]; -// body1_mat[2] = body1_trans.getBasis()[0][2]; -// body1_mat[4] = body1_trans.getBasis()[1][0]; -// body1_mat[5] = body1_trans.getBasis()[1][1]; -// body1_mat[6] = body1_trans.getBasis()[1][2]; -// body1_mat[8] = body1_trans.getBasis()[2][0]; -// body1_mat[9] = body1_trans.getBasis()[2][1]; -// body1_mat[10] = body1_trans.getBasis()[2][2]; - - - - - // anchor points in global coordinates with respect to body PORs. - - - int s = info->rowskip; - - // set jacobian - info->J1l[0] = 1; - info->J1l[s+1] = 1; - info->J1l[2*s+2] = 1; - - - btVector3 a1,a2; - - a1 = body0_trans.getBasis()*p2pconstraint->getPivotInA(); - //dMULTIPLY0_331 (a1, body0_mat,m_constraint->m_pivotInA); - dCROSSMAT (info->J1a,a1,s,-,+); - if (m_body1) - { - info->J2l[0] = -1; - info->J2l[s+1] = -1; - info->J2l[2*s+2] = -1; - a2 = body1_trans.getBasis()*p2pconstraint->getPivotInB(); - //dMULTIPLY0_331 (a2,body1_mat,m_constraint->m_pivotInB); - dCROSSMAT (info->J2a,a2,s,+,-); - } - - - // set right hand side - btScalar k = info->fps * info->erp; - if (m_body1) - { - for (int j=0; j<3; j++) - { - info->c[j] = k * (a2[j] + body1_trans.getOrigin()[j] - - a1[j] - body0_trans.getOrigin()[j]); - } - } - else - { - for (int j=0; j<3; j++) - { - info->c[j] = k * (p2pconstraint->getPivotInB()[j] - a1[j] - - body0_trans.getOrigin()[j]); - } - } -} - - -///////////////////limit motor support - -/*! \pre testLimitValue must be called on limot*/ -int bt_get_limit_motor_info2( - btRotationalLimitMotor * limot, - btRigidBody * body0, btRigidBody * body1, - btOdeJoint::Info2 *info, int row, btVector3& ax1, int rotational) -{ - - - int srow = row * info->rowskip; - - // if the joint is powered, or has joint limits, add in the extra row - int powered = limot->m_enableMotor; - int limit = limot->m_currentLimit; - - if (powered || limit) - { - btScalar *J1 = rotational ? info->J1a : info->J1l; - btScalar *J2 = rotational ? info->J2a : info->J2l; - - J1[srow+0] = ax1[0]; - J1[srow+1] = ax1[1]; - J1[srow+2] = ax1[2]; - if (body1) - { - J2[srow+0] = -ax1[0]; - J2[srow+1] = -ax1[1]; - J2[srow+2] = -ax1[2]; - } - - // linear limot torque decoupling step: - // - // if this is a linear limot (e.g. from a slider), we have to be careful - // that the linear constraint forces (+/- ax1) applied to the two bodies - // do not create a torque couple. in other words, the points that the - // constraint force is applied at must lie along the same ax1 axis. - // a torque couple will result in powered or limited slider-jointed free - // bodies from gaining angular momentum. - // the solution used here is to apply the constraint forces at the point - // halfway between the body centers. there is no penalty (other than an - // extra tiny bit of computation) in doing this adjustment. note that we - // only need to do this if the constraint connects two bodies. - - btVector3 ltd; // Linear Torque Decoupling vector (a torque) - if (!rotational && body1) - { - btVector3 c; - c[0]=btScalar(0.5)*(body1->getCenterOfMassPosition()[0] - -body0->getCenterOfMassPosition()[0]); - c[1]=btScalar(0.5)*(body1->getCenterOfMassPosition()[1] - -body0->getCenterOfMassPosition()[1]); - c[2]=btScalar(0.5)*(body1->getCenterOfMassPosition()[2] - -body0->getCenterOfMassPosition()[2]); - - ltd = c.cross(ax1); - - info->J1a[srow+0] = ltd[0]; - info->J1a[srow+1] = ltd[1]; - info->J1a[srow+2] = ltd[2]; - info->J2a[srow+0] = ltd[0]; - info->J2a[srow+1] = ltd[1]; - info->J2a[srow+2] = ltd[2]; - } - - // if we're limited low and high simultaneously, the joint motor is - // ineffective - - if (limit && (limot->m_loLimit == limot->m_hiLimit)) powered = 0; - - if (powered) - { - info->cfm[row] = 0.0f;//limot->m_normalCFM; - if (! limit) - { - info->c[row] = limot->m_targetVelocity; - info->lo[row] = -limot->m_maxMotorForce; - info->hi[row] = limot->m_maxMotorForce; - } - } - - if (limit) - { - btScalar k = info->fps * limot->m_ERP; - info->c[row] = -k * limot->m_currentLimitError; - info->cfm[row] = 0.0f;//limot->m_stopCFM; - - if (limot->m_loLimit == limot->m_hiLimit) - { - // limited low and high simultaneously - info->lo[row] = -dInfinity; - info->hi[row] = dInfinity; - } - else - { - if (limit == 1) - { - // low limit - info->lo[row] = 0; - info->hi[row] = SIMD_INFINITY; - } - else - { - // high limit - info->lo[row] = -SIMD_INFINITY; - info->hi[row] = 0; - } - - // deal with bounce - if (limot->m_bounce > 0) - { - // calculate joint velocity - btScalar vel; - if (rotational) - { - vel = body0->getAngularVelocity().dot(ax1); - if (body1) - vel -= body1->getAngularVelocity().dot(ax1); - } - else - { - vel = body0->getLinearVelocity().dot(ax1); - if (body1) - vel -= body1->getLinearVelocity().dot(ax1); - } - - // only apply bounce if the velocity is incoming, and if the - // resulting c[] exceeds what we already have. - if (limit == 1) - { - // low limit - if (vel < 0) - { - btScalar newc = -limot->m_bounce* vel; - if (newc > info->c[row]) info->c[row] = newc; - } - } - else - { - // high limit - all those computations are reversed - if (vel > 0) - { - btScalar newc = -limot->m_bounce * vel; - if (newc < info->c[row]) info->c[row] = newc; - } - } - } - } - } - return 1; - } - else return 0; -} - - -///////////////////OdeD6Joint - - - - - -OdeD6Joint::OdeD6Joint( - btTypedConstraint * constraint, - int index,bool swap,btOdeSolverBody* body0,btOdeSolverBody* body1): - btOdeTypedJoint(constraint,index,swap,body0,body1) -{ -} - - -void OdeD6Joint::GetInfo1(Info1 *info) -{ - btGeneric6DofConstraint * d6constraint = this->getD6Constraint(); - //prepare constraint - d6constraint->calculateTransforms(); - info->m = 3; - info->nub = 3; - - //test angular limits - for (int i=0;i<3 ;i++ ) - { - //if(i==2) continue; - if(d6constraint->testAngularLimitMotor(i)) - { - info->m++; - } - } - - -} - - -int OdeD6Joint::setLinearLimits(Info2 *info) -{ - - btGeneric6DofConstraint * d6constraint = this->getD6Constraint(); - - //retrieve matrices - btTransform body0_trans; - if (m_body0) - { - body0_trans = m_body0->m_originalBody->getCenterOfMassTransform(); - } - - btTransform body1_trans; - - if (m_body1) - { - body1_trans = m_body1->m_originalBody->getCenterOfMassTransform(); - } - - // anchor points in global coordinates with respect to body PORs. - - int s = info->rowskip; - - // set jacobian - info->J1l[0] = 1; - info->J1l[s+1] = 1; - info->J1l[2*s+2] = 1; - - - btVector3 a1,a2; - - a1 = body0_trans.getBasis()*d6constraint->getFrameOffsetA().getOrigin(); - //dMULTIPLY0_331 (a1, body0_mat,m_constraint->m_pivotInA); - dCROSSMAT (info->J1a,a1,s,-,+); - if (m_body1) - { - info->J2l[0] = -1; - info->J2l[s+1] = -1; - info->J2l[2*s+2] = -1; - a2 = body1_trans.getBasis()*d6constraint->getFrameOffsetB().getOrigin(); - - //dMULTIPLY0_331 (a2,body1_mat,m_constraint->m_pivotInB); - dCROSSMAT (info->J2a,a2,s,+,-); - } - - - // set right hand side - btScalar k = info->fps * info->erp; - if (m_body1) - { - for (int j=0; j<3; j++) - { - info->c[j] = k * (a2[j] + body1_trans.getOrigin()[j] - - a1[j] - body0_trans.getOrigin()[j]); - } - } - else - { - for (int j=0; j<3; j++) - { - info->c[j] = k * (d6constraint->getCalculatedTransformB().getOrigin()[j] - a1[j] - - body0_trans.getOrigin()[j]); - } - } - - return 3; - -} - -int OdeD6Joint::setAngularLimits(Info2 *info, int row_offset) -{ - btGeneric6DofConstraint * d6constraint = this->getD6Constraint(); - int row = row_offset; - //solve angular limits - for (int i=0;i<3 ;i++ ) - { - //if(i==2) continue; - if(d6constraint->getRotationalLimitMotor(i)->needApplyTorques()) - { - btVector3 axis = d6constraint->getAxis(i); - row += bt_get_limit_motor_info2( - d6constraint->getRotationalLimitMotor(i), - m_body0->m_originalBody, - m_body1 ? m_body1->m_originalBody : NULL, - info,row,axis,1); - } - } - - return row; -} - -void OdeD6Joint::GetInfo2(Info2 *info) -{ - int row = setLinearLimits(info); - setAngularLimits(info, row); -} - -//---------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------- -/* -OdeSliderJoint -Ported from ODE by Roman Ponomarev (rponom@gmail.com) -April 24, 2008 -*/ - -OdeSliderJoint::OdeSliderJoint( - btTypedConstraint * constraint, - int index,bool swap, btOdeSolverBody* body0, btOdeSolverBody* body1): - btOdeTypedJoint(constraint,index,swap,body0,body1) -{ -} // OdeSliderJoint::OdeSliderJoint() - -//---------------------------------------------------------------------------------- - -void OdeSliderJoint::GetInfo1(Info1* info) -{ - info->nub = 4; - info->m = 4; // Fixed 2 linear + 2 angular - btSliderConstraint * slider = this->getSliderConstraint(); - //prepare constraint - slider->calculateTransforms(); - slider->testLinLimits(); - if(slider->getSolveLinLimit() || slider->getPoweredLinMotor()) - { - info->m++; // limit 3rd linear as well - } - slider->testAngLimits(); - if(slider->getSolveAngLimit() || slider->getPoweredAngMotor()) - { - info->m++; // limit 3rd angular as well - } -} // OdeSliderJoint::GetInfo1() - -//---------------------------------------------------------------------------------- - -void OdeSliderJoint::GetInfo2(Info2 *info) -{ - int i, s = info->rowskip; - btSliderConstraint * slider = this->getSliderConstraint(); - const btTransform& trA = slider->getCalculatedTransformA(); - const btTransform& trB = slider->getCalculatedTransformB(); - // make rotations around Y and Z equal - // the slider axis should be the only unconstrained - // rotational axis, the angular velocity of the two bodies perpendicular to - // the slider axis should be equal. thus the constraint equations are - // p*w1 - p*w2 = 0 - // q*w1 - q*w2 = 0 - // where p and q are unit vectors normal to the slider axis, and w1 and w2 - // are the angular velocity vectors of the two bodies. - // get slider axis (X) - btVector3 ax1 = trA.getBasis().getColumn(0); - // get 2 orthos to slider axis (Y, Z) - btVector3 p = trA.getBasis().getColumn(1); - btVector3 q = trA.getBasis().getColumn(2); - // set the two slider rows - info->J1a[0] = p[0]; - info->J1a[1] = p[1]; - info->J1a[2] = p[2]; - info->J1a[s+0] = q[0]; - info->J1a[s+1] = q[1]; - info->J1a[s+2] = q[2]; - if(m_body1) - { - info->J2a[0] = -p[0]; - info->J2a[1] = -p[1]; - info->J2a[2] = -p[2]; - info->J2a[s+0] = -q[0]; - info->J2a[s+1] = -q[1]; - info->J2a[s+2] = -q[2]; - } - // compute the right hand side of the constraint equation. set relative - // body velocities along p and q to bring the slider back into alignment. - // if ax1,ax2 are the unit length slider axes as computed from body1 and - // body2, we need to rotate both bodies along the axis u = (ax1 x ax2). - // if "theta" is the angle between ax1 and ax2, we need an angular velocity - // along u to cover angle erp*theta in one step : - // |angular_velocity| = angle/time = erp*theta / stepsize - // = (erp*fps) * theta - // angular_velocity = |angular_velocity| * (ax1 x ax2) / |ax1 x ax2| - // = (erp*fps) * theta * (ax1 x ax2) / sin(theta) - // ...as ax1 and ax2 are unit length. if theta is smallish, - // theta ~= sin(theta), so - // angular_velocity = (erp*fps) * (ax1 x ax2) - // ax1 x ax2 is in the plane space of ax1, so we project the angular - // velocity to p and q to find the right hand side. - btScalar k = info->fps * info->erp * slider->getSoftnessOrthoAng(); - btVector3 ax2 = trB.getBasis().getColumn(0); - btVector3 u; - if(m_body1) - { - u = ax1.cross(ax2); - } - else - { - u = ax2.cross(ax1); - } - info->c[0] = k * u.dot(p); - info->c[1] = k * u.dot(q); - // pull out pos and R for both bodies. also get the connection - // vector c = pos2-pos1. - // next two rows. we want: vel2 = vel1 + w1 x c ... but this would - // result in three equations, so we project along the planespace vectors - // so that sliding along the slider axis is disregarded. for symmetry we - // also substitute (w1+w2)/2 for w1, as w1 is supposed to equal w2. - btTransform bodyA_trans = m_body0->m_originalBody->getCenterOfMassTransform(); - btTransform bodyB_trans; - if(m_body1) - { - bodyB_trans = m_body1->m_originalBody->getCenterOfMassTransform(); - } - int s2 = 2 * s, s3 = 3 * s; - btVector3 c; - if(m_body1) - { - c = bodyB_trans.getOrigin() - bodyA_trans.getOrigin(); - btVector3 tmp = btScalar(0.5) * c.cross(p); - - for (i=0; i<3; i++) info->J1a[s2+i] = tmp[i]; - for (i=0; i<3; i++) info->J2a[s2+i] = tmp[i]; - - tmp = btScalar(0.5) * c.cross(q); - - for (i=0; i<3; i++) info->J1a[s3+i] = tmp[i]; - for (i=0; i<3; i++) info->J2a[s3+i] = tmp[i]; - - for (i=0; i<3; i++) info->J2l[s2+i] = -p[i]; - for (i=0; i<3; i++) info->J2l[s3+i] = -q[i]; - } - for (i=0; i<3; i++) info->J1l[s2+i] = p[i]; - for (i=0; i<3; i++) info->J1l[s3+i] = q[i]; - // compute two elements of right hand side. we want to align the offset - // point (in body 2's frame) with the center of body 1. - btVector3 ofs; // offset point in global coordinates - if(m_body1) - { - ofs = trB.getOrigin() - trA.getOrigin(); - } - else - { - ofs = trA.getOrigin() - trB.getOrigin(); - } - k = info->fps * info->erp * slider->getSoftnessOrthoLin(); - info->c[2] = k * p.dot(ofs); - info->c[3] = k * q.dot(ofs); - int nrow = 3; // last filled row - int srow; - // check linear limits linear - btScalar limit_err = btScalar(0.0); - int limit = 0; - if(slider->getSolveLinLimit()) - { - limit_err = slider->getLinDepth(); - if(m_body1) - { - limit = (limit_err > btScalar(0.0)) ? 1 : 2; - } - else - { - limit = (limit_err > btScalar(0.0)) ? 2 : 1; - } - } - int powered = 0; - if(slider->getPoweredLinMotor()) - { - powered = 1; - } - // if the slider has joint limits, add in the extra row - if (limit || powered) - { - nrow++; - srow = nrow * info->rowskip; - info->J1l[srow+0] = ax1[0]; - info->J1l[srow+1] = ax1[1]; - info->J1l[srow+2] = ax1[2]; - if(m_body1) - { - info->J2l[srow+0] = -ax1[0]; - info->J2l[srow+1] = -ax1[1]; - info->J2l[srow+2] = -ax1[2]; - } - // linear torque decoupling step: - // - // we have to be careful that the linear constraint forces (+/- ax1) applied to the two bodies - // do not create a torque couple. in other words, the points that the - // constraint force is applied at must lie along the same ax1 axis. - // a torque couple will result in limited slider-jointed free - // bodies from gaining angular momentum. - // the solution used here is to apply the constraint forces at the point - // halfway between the body centers. there is no penalty (other than an - // extra tiny bit of computation) in doing this adjustment. note that we - // only need to do this if the constraint connects two bodies. - if (m_body1) - { - dVector3 ltd; // Linear Torque Decoupling vector (a torque) - c = btScalar(0.5) * c; - dCROSS (ltd,=,c,ax1); - info->J1a[srow+0] = ltd[0]; - info->J1a[srow+1] = ltd[1]; - info->J1a[srow+2] = ltd[2]; - info->J2a[srow+0] = ltd[0]; - info->J2a[srow+1] = ltd[1]; - info->J2a[srow+2] = ltd[2]; - } - // right-hand part - btScalar lostop = slider->getLowerLinLimit(); - btScalar histop = slider->getUpperLinLimit(); - if(limit && (lostop == histop)) - { // the joint motor is ineffective - powered = 0; - } - if(powered) - { - info->cfm[nrow] = btScalar(0.0); - if(!limit) - { - info->c[nrow] = slider->getTargetLinMotorVelocity(); - info->lo[nrow] = -slider->getMaxLinMotorForce() * info->fps; - info->hi[nrow] = slider->getMaxLinMotorForce() * info->fps; - } - } - if(limit) - { - k = info->fps * info->erp; - if(m_body1) - { - info->c[nrow] = k * limit_err; - } - else - { - info->c[nrow] = - k * limit_err; - } - info->cfm[nrow] = btScalar(0.0); // stop_cfm; - if(lostop == histop) - { - // limited low and high simultaneously - info->lo[nrow] = -SIMD_INFINITY; - info->hi[nrow] = SIMD_INFINITY; - } - else - { - if(limit == 1) - { - // low limit - info->lo[nrow] = 0; - info->hi[nrow] = SIMD_INFINITY; - } - else - { - // high limit - info->lo[nrow] = -SIMD_INFINITY; - info->hi[nrow] = 0; - } - } - // bounce (we'll use slider parameter abs(1.0 - m_dampingLimLin) for that) - btScalar bounce = btFabs(btScalar(1.0) - slider->getDampingLimLin()); - if(bounce > btScalar(0.0)) - { - btScalar vel = m_body0->m_originalBody->getLinearVelocity().dot(ax1); - if(m_body1) - { - vel -= m_body1->m_originalBody->getLinearVelocity().dot(ax1); - } - // only apply bounce if the velocity is incoming, and if the - // resulting c[] exceeds what we already have. - if(limit == 1) - { - // low limit - if(vel < 0) - { - btScalar newc = -bounce * vel; - if (newc > info->c[nrow]) info->c[nrow] = newc; - } - } - else - { - // high limit - all those computations are reversed - if(vel > 0) - { - btScalar newc = -bounce * vel; - if(newc < info->c[nrow]) info->c[nrow] = newc; - } - } - } - info->c[nrow] *= slider->getSoftnessLimLin(); - } // if(limit) - } // if linear limit - // check angular limits - limit_err = btScalar(0.0); - limit = 0; - if(slider->getSolveAngLimit()) - { - limit_err = slider->getAngDepth(); - if(m_body1) - { - limit = (limit_err > btScalar(0.0)) ? 1 : 2; - } - else - { - limit = (limit_err > btScalar(0.0)) ? 2 : 1; - } - } - // if the slider has joint limits, add in the extra row - powered = 0; - if(slider->getPoweredAngMotor()) - { - powered = 1; - } - if(limit || powered) - { - nrow++; - srow = nrow * info->rowskip; - info->J1a[srow+0] = ax1[0]; - info->J1a[srow+1] = ax1[1]; - info->J1a[srow+2] = ax1[2]; - if(m_body1) - { - info->J2a[srow+0] = -ax1[0]; - info->J2a[srow+1] = -ax1[1]; - info->J2a[srow+2] = -ax1[2]; - } - btScalar lostop = slider->getLowerAngLimit(); - btScalar histop = slider->getUpperAngLimit(); - if(limit && (lostop == histop)) - { // the joint motor is ineffective - powered = 0; - } - if(powered) - { - info->cfm[nrow] = btScalar(0.0); - if(!limit) - { - info->c[nrow] = slider->getTargetAngMotorVelocity(); - info->lo[nrow] = -slider->getMaxAngMotorForce() * info->fps; - info->hi[nrow] = slider->getMaxAngMotorForce() * info->fps; - } - } - if(limit) - { - k = info->fps * info->erp; - if (m_body1) - { - info->c[nrow] = k * limit_err; - } - else - { - info->c[nrow] = -k * limit_err; - } - info->cfm[nrow] = btScalar(0.0); // stop_cfm; - if(lostop == histop) - { - // limited low and high simultaneously - info->lo[nrow] = -SIMD_INFINITY; - info->hi[nrow] = SIMD_INFINITY; - } - else - { - if (limit == 1) - { - // low limit - info->lo[nrow] = 0; - info->hi[nrow] = SIMD_INFINITY; - } - else - { - // high limit - info->lo[nrow] = -SIMD_INFINITY; - info->hi[nrow] = 0; - } - } - // bounce (we'll use slider parameter abs(1.0 - m_dampingLimAng) for that) - btScalar bounce = btFabs(btScalar(1.0) - slider->getDampingLimAng()); - if(bounce > btScalar(0.0)) - { - btScalar vel = m_body0->m_originalBody->getAngularVelocity().dot(ax1); - if(m_body1) - { - vel -= m_body1->m_originalBody->getAngularVelocity().dot(ax1); - } - // only apply bounce if the velocity is incoming, and if the - // resulting c[] exceeds what we already have. - if(limit == 1) - { - // low limit - if(vel < 0) - { - btScalar newc = -bounce * vel; - if (newc > info->c[nrow]) info->c[nrow] = newc; - } - } - else - { - // high limit - all those computations are reversed - if(vel > 0) - { - btScalar newc = -bounce * vel; - if(newc < info->c[nrow]) info->c[nrow] = newc; - } - } - } - info->c[nrow] *= slider->getSoftnessLimAng(); - } // if(limit) - } // if angular limit or powered -} // OdeSliderJoint::GetInfo2() - -//---------------------------------------------------------------------------------- -//---------------------------------------------------------------------------------- - - - - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeTypedJoint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeTypedJoint.h deleted file mode 100644 index a2affda382d..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btOdeTypedJoint.h +++ /dev/null @@ -1,142 +0,0 @@ -/* -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. -*/ -/* -2007-09-09 -Added support for typed joints by Francisco Le?n -email: projectileman@yahoo.com -http://gimpact.sf.net -*/ - -#ifndef TYPED_JOINT_H -#define TYPED_JOINT_H - -#include "btOdeJoint.h" -#include "BulletDynamics/ConstraintSolver/btPoint2PointConstraint.h" -#include "BulletDynamics/ConstraintSolver/btGeneric6DofConstraint.h" -#include "BulletDynamics/ConstraintSolver/btSliderConstraint.h" - -struct btOdeSolverBody; - -class btOdeTypedJoint : public btOdeJoint -{ -public: - btTypedConstraint * m_constraint; - int m_index; - bool m_swapBodies; - btOdeSolverBody* m_body0; - btOdeSolverBody* m_body1; - - btOdeTypedJoint(){} - btOdeTypedJoint( - btTypedConstraint * constraint, - int index,bool swap,btOdeSolverBody* body0,btOdeSolverBody* body1): - m_constraint(constraint), - m_index(index), - m_swapBodies(swap), - m_body0(body0), - m_body1(body1) - { - } - - virtual void GetInfo1(Info1 *info); - virtual void GetInfo2(Info2 *info); -}; - - - -class OdeP2PJoint : public btOdeTypedJoint -{ -protected: - inline btPoint2PointConstraint * getP2PConstraint() - { - return static_cast(m_constraint); - } -public: - - OdeP2PJoint() {}; - - OdeP2PJoint(btTypedConstraint* constraint,int index,bool swap,btOdeSolverBody* body0,btOdeSolverBody* body1); - - //btOdeJoint interface for solver - - virtual void GetInfo1(Info1 *info); - - virtual void GetInfo2(Info2 *info); -}; - - -class OdeD6Joint : public btOdeTypedJoint -{ -protected: - inline btGeneric6DofConstraint * getD6Constraint() - { - return static_cast(m_constraint); - } - - int setLinearLimits(Info2 *info); - int setAngularLimits(Info2 *info, int row_offset); - -public: - - OdeD6Joint() {}; - - OdeD6Joint(btTypedConstraint* constraint,int index,bool swap,btOdeSolverBody* body0,btOdeSolverBody* body1); - - //btOdeJoint interface for solver - - virtual void GetInfo1(Info1 *info); - - virtual void GetInfo2(Info2 *info); -}; - -//! retrieves the constraint info from a btRotationalLimitMotor object -/*! \pre testLimitValue must be called on limot*/ -int bt_get_limit_motor_info2( - btRotationalLimitMotor * limot, - btRigidBody * body0, btRigidBody * body1, - btOdeJoint::Info2 *info, int row, btVector3& ax1, int rotational); - -/* -OdeSliderJoint -Ported from ODE by Roman Ponomarev (rponom@gmail.com) -April 24, 2008 -*/ -class OdeSliderJoint : public btOdeTypedJoint -{ -protected: - inline btSliderConstraint * getSliderConstraint() - { - return static_cast(m_constraint); - } -public: - - OdeSliderJoint() {}; - - OdeSliderJoint(btTypedConstraint* constraint,int index,bool swap, btOdeSolverBody* body0, btOdeSolverBody* body1); - - //BU_Joint interface for solver - - virtual void GetInfo1(Info1 *info); - - virtual void GetInfo2(Info2 *info); -}; - - - - -#endif //CONTACT_JOINT_H - - - diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp index e7f07a428eb..4128f504bf1 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.cpp @@ -342,6 +342,7 @@ void btSliderConstraint::calculateTransforms(void){ void btSliderConstraint::testLinLimits(void) { m_solveLinLim = false; + m_linPos = m_depth[0]; if(m_lowerLinLimit <= m_upperLinLimit) { if(m_depth[0] > m_upperLinLimit) diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h index f69dfcf3aa7..580dfa1178d 100644 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h +++ b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSliderConstraint.h @@ -103,6 +103,8 @@ protected: btVector3 m_relPosA; btVector3 m_relPosB; + btScalar m_linPos; + btScalar m_angDepth; btScalar m_kAngle; @@ -191,6 +193,7 @@ public: btScalar getTargetAngMotorVelocity() { return m_targetAngMotorVelocity; } void setMaxAngMotorForce(btScalar maxAngMotorForce) { m_maxAngMotorForce = maxAngMotorForce; } btScalar getMaxAngMotorForce() { return m_maxAngMotorForce; } + btScalar getLinearPos() { return m_linPos; } // access for ODE solver bool getSolveLinLimit() { return m_solveLinLim; } diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSorLcp.cpp b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSorLcp.cpp deleted file mode 100644 index 175d15dcfcf..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSorLcp.cpp +++ /dev/null @@ -1,683 +0,0 @@ -/* - * Quickstep constraint solver re-distributed under the ZLib license with permission from Russell L. Smith - * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. - * All rights reserved. Email: russ@q12.org Web: www.q12.org - Bullet Continuous Collision Detection and Physics Library - Bullet is 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 "btSorLcp.h" -#include "btOdeSolverBody.h" - -#ifdef USE_SOR_SOLVER - -// SOR LCP taken from ode quickstep, for comparisons to Bullet sequential impulse solver. -#include "LinearMath/btScalar.h" - -#include "BulletDynamics/Dynamics/btRigidBody.h" -#include -#include //FLT_MAX -#ifdef WIN32 -#include -#endif -#include -#include - -#if defined (WIN32) -#include -#else -#if defined (__FreeBSD__) -#include -#else -#include -#endif -#endif - -#include "btOdeJoint.h" -#include "BulletDynamics/ConstraintSolver/btContactSolverInfo.h" -//////////////////////////////////////////////////////////////////// -//math stuff -#include "btOdeMacros.h" - -//*************************************************************************** -// configuration - -// for the SOR and CG methods: -// uncomment the following line to use warm starting. this definitely -// help for motor-driven joints. unfortunately it appears to hurt -// with high-friction contacts using the SOR method. use with care - -//#define WARM_STARTING 1 - -// for the SOR method: -// uncomment the following line to randomly reorder constraint rows -// during the solution. depending on the situation, this can help a lot -// or hardly at all, but it doesn't seem to hurt. - -#define RANDOMLY_REORDER_CONSTRAINTS 1 - -//*************************************************************************** -// various common computations involving the matrix J -// compute iMJ = inv(M)*J' -inline void compute_invM_JT (int m, dRealMutablePtr J, dRealMutablePtr iMJ, int *jb, - //OdeSolverBody* const *body, - const btAlignedObjectArray &body, - dRealPtr invI) -{ - int i,j; - dRealMutablePtr iMJ_ptr = iMJ; - dRealMutablePtr J_ptr = J; - for (i=0; im_invMass; - for (j=0; j<3; j++) iMJ_ptr[j] = k*J_ptr[j]; - dMULTIPLY0_331 (iMJ_ptr + 3, invI + 12*b1, J_ptr + 3); - if (b2 >= 0) { - k = body[b2]->m_invMass; - for (j=0; j<3; j++) iMJ_ptr[j+6] = k*J_ptr[j+6]; - dMULTIPLY0_331 (iMJ_ptr + 9, invI + 12*b2, J_ptr + 9); - } - J_ptr += 12; - iMJ_ptr += 12; - } -} - -#if 0 -static void multiply_invM_JTSpecial (int m, int nb, dRealMutablePtr iMJ, int *jb, - dRealMutablePtr in, dRealMutablePtr out,int onlyBody1,int onlyBody2) -{ - int i,j; - - - - dRealMutablePtr out_ptr1 = out + onlyBody1*6; - - for (j=0; j<6; j++) - out_ptr1[j] = 0; - - if (onlyBody2 >= 0) - { - out_ptr1 = out + onlyBody2*6; - - for (j=0; j<6; j++) - out_ptr1[j] = 0; - } - - dRealPtr iMJ_ptr = iMJ; - for (i=0; i= 0) - { - out_ptr = out + b2*6; - for (j=0; j<6; j++) - out_ptr[j] += iMJ_ptr[j] * in[i]; - } - } - - iMJ_ptr += 6; - - } -} -#endif - - -// compute out = inv(M)*J'*in. - -#if 0 -static void multiply_invM_JT (int m, int nb, dRealMutablePtr iMJ, int *jb, - dRealMutablePtr in, dRealMutablePtr out) -{ - int i,j; - dSetZero1 (out,6*nb); - dRealPtr iMJ_ptr = iMJ; - for (i=0; i= 0) { - out_ptr = out + b2*6; - for (j=0; j<6; j++) out_ptr[j] += iMJ_ptr[j] * in[i]; - } - iMJ_ptr += 6; - } -} -#endif - - -// compute out = J*in. -inline void multiply_J (int m, dRealMutablePtr J, int *jb, - dRealMutablePtr in, dRealMutablePtr out) -{ - int i,j; - dRealPtr J_ptr = J; - for (i=0; i= 0) { - in_ptr = in + b2*6; - for (j=0; j<6; j++) sum += J_ptr[j] * in_ptr[j]; - } - J_ptr += 6; - out[i] = sum; - } -} - -//*************************************************************************** -// SOR-LCP method - -// nb is the number of bodies in the body array. -// J is an m*12 matrix of constraint rows -// jb is an array of first and second body numbers for each constraint row -// invI is the global frame inverse inertia for each body (stacked 3x3 matrices) -// -// this returns lambda and fc (the constraint force). -// note: fc is returned as inv(M)*J'*lambda, the constraint force is actually J'*lambda -// -// b, lo and hi are modified on exit - -//------------------------------------------------------------------------------ -ATTRIBUTE_ALIGNED16(struct) IndexError { - btScalar error; // error to sort on - int findex; - int index; // row index -}; - -//------------------------------------------------------------------------------ -void btSorLcpSolver::SOR_LCP(int m, int nb, dRealMutablePtr J, int *jb, - const btAlignedObjectArray &body, - dRealPtr invI, dRealMutablePtr lambda, dRealMutablePtr invMforce, dRealMutablePtr rhs, - dRealMutablePtr lo, dRealMutablePtr hi, dRealPtr cfm, int *findex, - int numiter,float overRelax, - btStackAlloc* stackAlloc - ) -{ - //btBlock* saBlock = stackAlloc->beginBlock();//Remo: 10.10.2007 - AutoBlockSa asaBlock(stackAlloc); - - const int num_iterations = numiter; - const float sor_w = overRelax; // SOR over-relaxation parameter - - int i,j; - -#ifdef WARM_STARTING - // for warm starting, this seems to be necessary to prevent - // jerkiness in motor-driven joints. i have no idea why this works. - for (i=0; i= 0) { - for (j=6; j<12; j++) sum += iMJ_ptr[j] * J_ptr[j]; - } - iMJ_ptr += 12; - J_ptr += 12; - Ad[i] = sor_w / sum;//(sum + cfm[i]); - } - - // scale J and b by Ad - J_ptr = J; - for (i=0; i= 0) - order[j++].index = i; - dIASSERT (j==m); -#endif - - for (int iteration=0; iteration < num_iterations; iteration++) { - -#ifdef REORDER_CONSTRAINTS - // constraints with findex < 0 always come first. - if (iteration < 2) { - // for the first two iterations, solve the constraints in - // the given order - for (i=0; i v2) ? v1 : v2; - if (max > 0) { - //@@@ relative error: order[i].error = dFabs(lambda[i]-last_lambda[i])/max; - order[i].error = dFabs(lambda[i]-last_lambda[i]); - } - else { - order[i].error = dInfinity; - } - order[i].findex = findex[i]; - order[i].index = i; - } - } - qsort (order,m,sizeof(IndexError),&compare_index_error); -#endif -#ifdef RANDOMLY_REORDER_CONSTRAINTS - if ((iteration & 7) == 0) { - for (i=1; i= 0) { - hi[index] = btFabs (hicopy[index] * lambda[findex[index]]); - lo[index] = -hi[index]; - } - - int b1 = jb[index*2]; - int b2 = jb[index*2+1]; - float delta = rhs[index] - lambda[index]*Ad[index]; - dRealMutablePtr fc_ptr = invMforce + 6*b1; - - // @@@ potential optimization: SIMD-ize this and the b2 >= 0 case - delta -=fc_ptr[0] * J_ptr[0] + fc_ptr[1] * J_ptr[1] + - fc_ptr[2] * J_ptr[2] + fc_ptr[3] * J_ptr[3] + - fc_ptr[4] * J_ptr[4] + fc_ptr[5] * J_ptr[5]; - // @@@ potential optimization: handle 1-body constraints in a separate - // loop to avoid the cost of test & jump? - if (b2 >= 0) { - fc_ptr = invMforce + 6*b2; - delta -=fc_ptr[0] * J_ptr[6] + fc_ptr[1] * J_ptr[7] + - fc_ptr[2] * J_ptr[8] + fc_ptr[3] * J_ptr[9] + - fc_ptr[4] * J_ptr[10] + fc_ptr[5] * J_ptr[11]; - } - - // compute lambda and clamp it to [lo,hi]. - // @@@ potential optimization: does SSE have clamping instructions - // to save test+jump penalties here? - float new_lambda = lambda[index] + delta; - if (new_lambda < lo[index]) { - delta = lo[index]-lambda[index]; - lambda[index] = lo[index]; - } - else if (new_lambda > hi[index]) { - delta = hi[index]-lambda[index]; - lambda[index] = hi[index]; - } - else { - lambda[index] = new_lambda; - } - - //@@@ a trick that may or may not help - //float ramp = (1-((float)(iteration+1)/(float)num_iterations)); - //delta *= ramp; - - // update invMforce. - // @@@ potential optimization: SIMD for this and the b2 >= 0 case - fc_ptr = invMforce + 6*b1; - fc_ptr[0] += delta * iMJ_ptr[0]; - fc_ptr[1] += delta * iMJ_ptr[1]; - fc_ptr[2] += delta * iMJ_ptr[2]; - fc_ptr[3] += delta * iMJ_ptr[3]; - fc_ptr[4] += delta * iMJ_ptr[4]; - fc_ptr[5] += delta * iMJ_ptr[5]; - // @@@ potential optimization: handle 1-body constraints in a separate - // loop to avoid the cost of test & jump? - if (b2 >= 0) { - fc_ptr = invMforce + 6*b2; - fc_ptr[0] += delta * iMJ_ptr[6]; - fc_ptr[1] += delta * iMJ_ptr[7]; - fc_ptr[2] += delta * iMJ_ptr[8]; - fc_ptr[3] += delta * iMJ_ptr[9]; - fc_ptr[4] += delta * iMJ_ptr[10]; - fc_ptr[5] += delta * iMJ_ptr[11]; - } - } - } - //stackAlloc->endBlock(saBlock);//Remo: 10.10.2007 -} - -//------------------------------------------------------------------------------ -void btSorLcpSolver::SolveInternal1 ( - float global_cfm, - float global_erp, - const btAlignedObjectArray &body, int nb, - btAlignedObjectArray &joint, - int nj, const btContactSolverInfo& solverInfo, - btStackAlloc* stackAlloc) -{ - //btBlock* saBlock = stackAlloc->beginBlock();//Remo: 10.10.2007 - AutoBlockSa asaBlock(stackAlloc); - - int numIter = solverInfo.m_numIterations; - float sOr = solverInfo.m_sor; - - int i,j; - - btScalar stepsize1 = dRecip(solverInfo.m_timeStep); - - // number all bodies in the body list - set their tag values - for (i=0; im_odeTag = i; - - // make a local copy of the joint array, because we might want to modify it. - // (the "btOdeJoint *const*" declaration says we're allowed to modify the joints - // but not the joint array, because the caller might need it unchanged). - //@@@ do we really need to do this? we'll be sorting constraint rows individually, not joints - //btOdeJoint **joint = (btOdeJoint**) alloca (nj * sizeof(btOdeJoint*)); - //memcpy (joint,_joint,nj * sizeof(btOdeJoint*)); - - // for all bodies, compute the inertia tensor and its inverse in the global - // frame, and compute the rotational force and add it to the torque - // accumulator. I and invI are a vertical stack of 3x4 matrices, one per body. - dRealAllocaArray (I,3*4*nb); - dRealAllocaArray (invI,3*4*nb); -/* for (i=0; im_I,body[i]->m_R); - // compute inverse inertia tensor in global frame - dMULTIPLY2_333 (tmp,body[i]->m_invI,body[i]->m_R); - dMULTIPLY0_333 (invI+i*12,body[i]->m_R,tmp); - // compute rotational force - dCROSS (body[i]->m_tacc,-=,body[i]->getAngularVelocity(),tmp); - } -*/ - for (i=0; im_I,body[i]->m_R); - dMULTIPLY0_333 (I+i*12,body[i]->m_R,tmp); - - // compute inverse inertia tensor in global frame - dMULTIPLY2_333 (tmp,body[i]->m_invI,body[i]->m_R); - dMULTIPLY0_333 (invI+i*12,body[i]->m_R,tmp); - // compute rotational force -// dMULTIPLY0_331 (tmp,I+i*12,body[i]->m_angularVelocity); -// dCROSS (body[i]->m_tacc,-=,body[i]->m_angularVelocity,tmp); - } - - - - - // get joint information (m = total constraint dimension, nub = number of unbounded variables). - // joints with m=0 are inactive and are removed from the joints array - // entirely, so that the code that follows does not consider them. - //@@@ do we really need to save all the info1's - btOdeJoint::Info1 *info = (btOdeJoint::Info1*) ALLOCA (nj*sizeof(btOdeJoint::Info1)); - - for (i=0, j=0; jGetInfo1 (info+i); - dIASSERT (info[i].m >= 0 && info[i].m <= 6 && info[i].nub >= 0 && info[i].nub <= info[i].m); - if (info[i].m > 0) { - joint[i] = joint[j]; - i++; - } - } - nj = i; - - // create the row offset array - int m = 0; - int *ofs = (int*) ALLOCA (nj*sizeof(int)); - for (i=0; i 0) { - // create a constraint equation right hand side vector `c', a constraint - // force mixing vector `cfm', and LCP low and high bound vectors, and an - // 'findex' vector. - dRealAllocaArray (c,m); - dRealAllocaArray (cfm,m); - dRealAllocaArray (lo,m); - dRealAllocaArray (hi,m); - - int *findex = (int*) ALLOCA (m*sizeof(int)); - - dSetZero1 (c,m); - dSetValue1 (cfm,m,global_cfm); - dSetValue1 (lo,m,-dInfinity); - dSetValue1 (hi,m, dInfinity); - for (i=0; iGetInfo2 (&Jinfo); - - if (Jinfo.c[0] > solverInfo.m_maxErrorReduction) - Jinfo.c[0] = solverInfo.m_maxErrorReduction; - - // adjust returned findex values for global index numbering - for (j=0; j= 0) - findex[ofs[i] + j] += ofs[i]; - } - } - - // create an array of body numbers for each joint row - int *jb_ptr = jb; - for (i=0; inode[0].body) ? (joint[i]->node[0].body->m_odeTag) : -1; - int b2 = (joint[i]->node[1].body) ? (joint[i]->node[1].body->m_odeTag) : -1; - for (j=0; jm_invMass; - for (j=0; j<3; j++) - tmp1[i*6+j] = body[i]->m_facc[j] * body_invMass + body[i]->m_linearVelocity[j] * stepsize1; - dMULTIPLY0_331NEW (tmp1 + i*6 + 3,=,invI + i*12,body[i]->m_tacc); - for (j=0; j<3; j++) - tmp1[i*6+3+j] += body[i]->m_angularVelocity[j] * stepsize1; - } - - // put J*tmp1 into rhs - dRealAllocaArray (rhs,m); - multiply_J (m,J,jb,tmp1,rhs); - - // complete rhs - for (i=0; ilambda,info[i].m * sizeof(btScalar)); - } -#endif - - // solve the LCP problem and get lambda and invM*constraint_force - dRealAllocaArray (cforce,nb*6); - - /// SOR_LCP - SOR_LCP (m,nb,J,jb,body,invI,lambda,cforce,rhs,lo,hi,cfm,findex,numIter,sOr,stackAlloc); - -#ifdef WARM_STARTING - // save lambda for the next iteration - //@@@ note that this doesn't work for contact joints yet, as they are - // recreated every iteration - for (i=0; ilambda,lambda+ofs[i],info[i].m * sizeof(btScalar)); - } -#endif - - // note that the SOR method overwrites rhs and J at this point, so - // they should not be used again. - // add stepsize * cforce to the body velocity - for (i=0; im_linearVelocity[j] += solverInfo.m_timeStep* cforce[i*6+j]; - for (j=0; j<3; j++) - body[i]->m_angularVelocity[j] += solverInfo.m_timeStep* cforce[i*6+3+j]; - - } - } - - // compute the velocity update: - // add stepsize * invM * fe to the body velocity - for (i=0; im_invMass; - btVector3 linvel = body[i]->m_linearVelocity; - btVector3 angvel = body[i]->m_angularVelocity; - - for (j=0; j<3; j++) - { - linvel[j] += solverInfo.m_timeStep * body_invMass * body[i]->m_facc[j]; - } - for (j=0; j<3; j++) - { - body[i]->m_tacc[j] *= solverInfo.m_timeStep; - } - dMULTIPLY0_331NEW(angvel,+=,invI + i*12,body[i]->m_tacc); - body[i]->m_angularVelocity = angvel; - } - //stackAlloc->endBlock(saBlock);//Remo: 10.10.2007 -} - - -#endif //USE_SOR_SOLVER diff --git a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSorLcp.h b/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSorLcp.h deleted file mode 100644 index 0d3583d33d9..00000000000 --- a/extern/bullet2/src/BulletDynamics/ConstraintSolver/btSorLcp.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Quickstep constraint solver re-distributed under the ZLib license with permission from Russell L. Smith - * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. - * All rights reserved. Email: russ@q12.org Web: www.q12.org - Bullet Continuous Collision Detection and Physics Library - Bullet is 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. -*/ - -#define USE_SOR_SOLVER -#ifdef USE_SOR_SOLVER - -#ifndef SOR_LCP_H -#define SOR_LCP_H -struct btOdeSolverBody; -class btOdeJoint; -#include "LinearMath/btScalar.h" -#include "LinearMath/btAlignedObjectArray.h" -#include "LinearMath/btStackAlloc.h" - -struct btContactSolverInfo; - - -//============================================================================= -class btSorLcpSolver //Remotion: 11.10.2007 -{ -public: - btSorLcpSolver() - { - dRand2_seed = 0; - } - - void SolveInternal1 (float global_cfm, - float global_erp, - const btAlignedObjectArray &body, int nb, - btAlignedObjectArray &joint, - int nj, const btContactSolverInfo& solverInfo, - btStackAlloc* stackAlloc - ); - -public: //data - unsigned long dRand2_seed; - -protected: //typedef - typedef const btScalar *dRealPtr; - typedef btScalar *dRealMutablePtr; - -protected: //members - //------------------------------------------------------------------------------ - SIMD_FORCE_INLINE unsigned long dRand2() - { - dRand2_seed = (1664525L*dRand2_seed + 1013904223L) & 0xffffffff; - return dRand2_seed; - } - //------------------------------------------------------------------------------ - SIMD_FORCE_INLINE int dRandInt2 (int n) - { - float a = float(n) / 4294967296.0f; - return (int) (float(dRand2()) * a); - } - //------------------------------------------------------------------------------ - void SOR_LCP(int m, int nb, dRealMutablePtr J, int *jb, - const btAlignedObjectArray &body, - dRealPtr invI, dRealMutablePtr lambda, dRealMutablePtr invMforce, dRealMutablePtr rhs, - dRealMutablePtr lo, dRealMutablePtr hi, dRealPtr cfm, int *findex, - int numiter,float overRelax, - btStackAlloc* stackAlloc - ); -}; - - -//============================================================================= -class AutoBlockSa //Remotion: 10.10.2007 -{ - btStackAlloc* stackAlloc; - btBlock* saBlock; -public: - AutoBlockSa(btStackAlloc* stackAlloc_) - { - stackAlloc = stackAlloc_; - saBlock = stackAlloc->beginBlock(); - } - ~AutoBlockSa() - { - stackAlloc->endBlock(saBlock); - } - //operator btBlock* () { return saBlock; } -}; -// //Usage -//void function(btStackAlloc* stackAlloc) -//{ -// AutoBlockSa(stackAlloc); -// ... -// if(...) return; -// return; -//} -//------------------------------------------------------------------------------ - - -#endif //SOR_LCP_H - -#endif //USE_SOR_SOLVER - diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp index c7b1af245e9..e46c4e6136b 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.cpp @@ -269,7 +269,7 @@ void btDiscreteDynamicsWorld::synchronizeMotionStates() { btTransform interpolatedTransform; btTransformUtil::integrateTransform(body->getInterpolationWorldTransform(), - body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),m_localTime,interpolatedTransform); + body->getInterpolationLinearVelocity(),body->getInterpolationAngularVelocity(),m_localTime*body->getHitFraction(),interpolatedTransform); body->getMotionState()->setWorldTransform(interpolatedTransform); } } @@ -708,7 +708,78 @@ void btDiscreteDynamicsWorld::calculateSimulationIslands() } +#include "BulletCollision/BroadphaseCollision/btCollisionAlgorithm.h" +class btClosestNotMeConvexResultCallback : public btCollisionWorld::ClosestConvexResultCallback +{ + btCollisionObject* m_me; + btScalar m_allowedPenetration; + btOverlappingPairCache* m_pairCache; + + +public: + btClosestNotMeConvexResultCallback (btCollisionObject* me,const btVector3& fromA,const btVector3& toA,btOverlappingPairCache* pairCache) : + btCollisionWorld::ClosestConvexResultCallback(fromA,toA), + m_allowedPenetration(0.0f), + m_me(me), + m_pairCache(pairCache) + { + } + + virtual btScalar addSingleResult(btCollisionWorld::LocalConvexResult& convexResult,bool normalInWorldSpace) + { + if (convexResult.m_hitCollisionObject == m_me) + return 1.0; + + btVector3 linVelA,linVelB; + linVelA = m_convexToWorld-m_convexFromWorld; + linVelB = btVector3(0,0,0);//toB.getOrigin()-fromB.getOrigin(); + + btVector3 relativeVelocity = (linVelA-linVelB); + //don't report time of impact for motion away from the contact normal (or causes minor penetration) + if (convexResult.m_hitNormalLocal.dot(relativeVelocity)>=-m_allowedPenetration) + return 1.f; + + return ClosestConvexResultCallback::addSingleResult (convexResult, normalInWorldSpace); + } + + virtual bool needsCollision(btBroadphaseProxy* proxy0) const + { + //don't collide with itself + if (proxy0->m_clientObject == m_me) + return false; + + ///don't do CCD when the collision filters are not matching + if (!btCollisionWorld::ClosestConvexResultCallback::needsCollision(proxy0)) + return false; + + ///don't do CCD when there are already contact points (touching contact/penetration) + btAlignedObjectArray manifoldArray; + btBroadphasePair* collisionPair = m_pairCache->findPair(m_me->getBroadphaseHandle(),proxy0); + if (collisionPair) + { + if (collisionPair->m_algorithm) + { + manifoldArray.resize(0); + collisionPair->m_algorithm->getAllContactManifolds(manifoldArray); + for (int j=0;jgetNumContacts()>0) + return false; + } + } + } + return true; + } + + +}; + +///internal debugging variable. this value shouldn't be too high +int gNumClampedCcdMotions=0; + +//#include "stdio.h" void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) { BT_PROFILE("integrateTransforms"); @@ -719,9 +790,34 @@ void btDiscreteDynamicsWorld::integrateTransforms(btScalar timeStep) btRigidBody* body = btRigidBody::upcast(colObj); if (body) { + body->setHitFraction(1.f); + if (body->isActive() && (!body->isStaticOrKinematicObject())) { body->predictIntegratedTransform(timeStep, predictedTrans); + btScalar squareMotion = (predictedTrans.getOrigin()-body->getWorldTransform().getOrigin()).length2(); + + if (body->getCcdSquareMotionThreshold() && body->getCcdSquareMotionThreshold() < squareMotion) + { + BT_PROFILE("CCD motion clamping"); + if (body->getCollisionShape()->isConvex()) + { + gNumClampedCcdMotions++; + + btClosestNotMeConvexResultCallback sweepResults(body,body->getWorldTransform().getOrigin(),predictedTrans.getOrigin(),getBroadphase()->getOverlappingPairCache()); + btConvexShape* convexShape = static_cast(body->getCollisionShape()); + btSphereShape tmpSphere(body->getCcdSweptSphereRadius());//btConvexShape* convexShape = static_cast(body->getCollisionShape()); + convexSweepTest(&tmpSphere,body->getWorldTransform(),predictedTrans,sweepResults); + if (sweepResults.hasHit() && (sweepResults.m_closestHitFraction < 1.f)) + { + body->setHitFraction(sweepResults.m_closestHitFraction); + body->predictIntegratedTransform(timeStep*body->getHitFraction(), predictedTrans); + body->setHitFraction(0.f); +// printf("clamped integration to hit fraction = %f\n",fraction); + } + } + } + body->proceedToTransform( predictedTrans); } } diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h index d206a604960..d9e2652aaf6 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDiscreteDynamicsWorld.h @@ -59,7 +59,7 @@ protected: virtual void predictUnconstraintMotion(btScalar timeStep); - void integrateTransforms(btScalar timeStep); + virtual void integrateTransforms(btScalar timeStep); void calculateSimulationIslands(); diff --git a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h index dd9dfa71b7f..929e24d337c 100644 --- a/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h +++ b/extern/bullet2/src/BulletDynamics/Dynamics/btDynamicsWorld.h @@ -60,7 +60,7 @@ public: ///By default, Bullet will subdivide the timestep in constant substeps of each 'fixedTimeStep'. ///in order to keep the simulation real-time, the maximum number of substeps can be clamped to 'maxSubSteps'. ///You can disable subdividing the timestep/substepping by passing maxSubSteps=0 as second argument to stepSimulation, but in that case you have to keep the timeStep constant. - virtual int stepSimulation( btScalar timeStep,int maxSubSteps=10, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0; + virtual int stepSimulation( btScalar timeStep,int maxSubSteps=1, btScalar fixedTimeStep=btScalar(1.)/btScalar(60.))=0; virtual void debugDrawWorld() = 0; diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp index dfb48e2ff2d..2553009fec2 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp @@ -2002,7 +2002,7 @@ for(i=0;im_x); mx.setMax(c.m_nodes[j]->m_x); } - const btDbvtVolume bounds=btDbvtVolume::FromMM(mi,mx); + const ATTRIBUTE_ALIGNED16(btDbvtVolume) bounds=btDbvtVolume::FromMM(mi,mx); if(c.m_leaf) m_cdbvt.update(c.m_leaf,bounds,c.m_lv*m_sst.sdt*3,m_sst.radmrg); else @@ -2532,7 +2532,7 @@ switch(m_cfg.collisions&fCollision::RVSmask) const btScalar basemargin=getCollisionShape()->getMargin(); btVector3 mins; btVector3 maxs; - btDbvtVolume volume; + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume; pco->getCollisionShape()->getAabb( pco->getInterpolationWorldTransform(), mins, maxs); diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp index e9ec81f4d2c..d9919967233 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp @@ -373,7 +373,6 @@ void btSoftBodyHelpers::DrawInfos( btSoftBody* psb, bool areas, bool /*stress*/) { - /* for(int i=0;im_nodes.size();++i) { const btSoftBody::Node& n=psb->m_nodes[i]; @@ -391,8 +390,6 @@ void btSoftBodyHelpers::DrawInfos( btSoftBody* psb, } if(text[0]) idraw->draw3dText(n.m_x,text); } - */ - } // diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h b/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h index 0c87770d714..1a7be2cb840 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyInternals.h @@ -750,7 +750,8 @@ struct btSoftColliders friction = btMin(psb->m_cfg.kDF,prb->getFriction()); btVector3 mins; btVector3 maxs; - btDbvtVolume volume; + + ATTRIBUTE_ALIGNED16(btDbvtVolume) volume; pr->getCollisionShape()->getAabb(pr->getInterpolationWorldTransform(),mins,maxs); volume=btDbvtVolume::FromMM(mins,maxs); volume.Expand(btVector3(1,1,1)*margin); diff --git a/extern/bullet2/src/LinearMath/CMakeLists.txt b/extern/bullet2/src/LinearMath/CMakeLists.txt index 207eed94a3e..02ffaad7228 100644 --- a/extern/bullet2/src/LinearMath/CMakeLists.txt +++ b/extern/bullet2/src/LinearMath/CMakeLists.txt @@ -4,7 +4,32 @@ ${BULLET_PHYSICS_SOURCE_DIR}/src } ) ADD_LIBRARY(LibLinearMath -btQuickprof.cpp -btGeometryUtil.cpp + btAlignedObjectArray.h + btList.h + btPoolAllocator.h + btRandom.h + btVector3.h + btDefaultMotionState.h + btMatrix3x3.h + btQuadWord.h + btHashMap.h + btScalar.h + btAabbUtil2.h + btConvexHull.h + btConvexHull.cpp + btMinMax.h + btQuaternion.h + btStackAlloc.h + btGeometryUtil.h + btMotionState.h + btTransform.h + btAlignedAllocator.h + btIDebugDraw.h + btPoint3.h + btQuickprof.h + btTransformUtil.h + btQuickprof.cpp + btGeometryUtil.cpp + btAlignedAllocator.cpp ) diff --git a/extern/bullet2/src/LinearMath/btAabbUtil2.h b/extern/bullet2/src/LinearMath/btAabbUtil2.h index 8bb6b3af7c3..275c4914628 100644 --- a/extern/bullet2/src/LinearMath/btAabbUtil2.h +++ b/extern/bullet2/src/LinearMath/btAabbUtil2.h @@ -17,6 +17,7 @@ subject to the following restrictions: #ifndef AABB_UTIL2 #define AABB_UTIL2 +#include "btTransform.h" #include "btVector3.h" #include "btMinMax.h" @@ -163,6 +164,39 @@ SIMD_FORCE_INLINE bool btRayAabb(const btVector3& rayFrom, } + +SIMD_FORCE_INLINE void btTransformAabb(const btVector3& halfExtents, btScalar margin,const btTransform& t,btVector3& aabbMinOut,btVector3& aabbMaxOut) +{ + btVector3 halfExtentsWithMargin = halfExtents+btVector3(margin,margin,margin); + btMatrix3x3 abs_b = t.getBasis().absolute(); + btVector3 center = t.getOrigin(); + btVector3 extent = btVector3(abs_b[0].dot(halfExtentsWithMargin), + abs_b[1].dot(halfExtentsWithMargin), + abs_b[2].dot(halfExtentsWithMargin)); + aabbMinOut = center - extent; + aabbMaxOut = center + extent; +} + + +SIMD_FORCE_INLINE void btTransformAabb(const btVector3& localAabbMin,const btVector3& localAabbMax, btScalar margin,const btTransform& trans,btVector3& aabbMinOut,btVector3& aabbMaxOut) +{ + btAssert(localAabbMin.getX() <= localAabbMax.getX()); + btAssert(localAabbMin.getY() <= localAabbMax.getY()); + btAssert(localAabbMin.getZ() <= localAabbMax.getZ()); + btVector3 localHalfExtents = btScalar(0.5)*(localAabbMax-localAabbMin); + localHalfExtents+=btVector3(margin,margin,margin); + + btVector3 localCenter = btScalar(0.5)*(localAabbMax+localAabbMin); + btMatrix3x3 abs_b = trans.getBasis().absolute(); + btVector3 center = trans(localCenter); + btVector3 extent = btVector3(abs_b[0].dot(localHalfExtents), + abs_b[1].dot(localHalfExtents), + abs_b[2].dot(localHalfExtents)); + aabbMinOut = center-extent; + aabbMaxOut = center+extent; +} + + #endif diff --git a/extern/bullet2/src/LinearMath/btMatrix3x3.h b/extern/bullet2/src/LinearMath/btMatrix3x3.h index ca1a801402f..14aa4ae2348 100644 --- a/extern/bullet2/src/LinearMath/btMatrix3x3.h +++ b/extern/bullet2/src/LinearMath/btMatrix3x3.h @@ -284,6 +284,91 @@ class btMatrix3x3 { } + ///diagonalizes this matrix by the Jacobi method. rot stores the rotation + ///from the coordinate system in which the matrix is diagonal to the original + ///coordinate system, i.e., old_this = rot * new_this * rot^T. The iteration + ///stops when all off-diagonal elements are less than the threshold multiplied + ///by the sum of the absolute values of the diagonal, or when maxSteps have + ///been executed. Note that this matrix is assumed to be symmetric. + void diagonalize(btMatrix3x3& rot, btScalar threshold, int maxSteps) + { + rot.setIdentity(); + for (int step = maxSteps; step > 0; step--) + { + // find off-diagonal element [p][q] with largest magnitude + int p = 0; + int q = 1; + int r = 2; + btScalar max = btFabs(m_el[0][1]); + btScalar v = btFabs(m_el[0][2]); + if (v > max) + { + q = 2; + r = 1; + max = v; + } + v = btFabs(m_el[1][2]); + if (v > max) + { + p = 1; + q = 2; + r = 0; + max = v; + } + + btScalar t = threshold * (btFabs(m_el[0][0]) + btFabs(m_el[1][1]) + btFabs(m_el[2][2])); + if (max <= t) + { + if (max <= SIMD_EPSILON * t) + { + return; + } + step = 1; + } + + // compute Jacobi rotation J which leads to a zero for element [p][q] + btScalar mpq = m_el[p][q]; + btScalar theta = (m_el[q][q] - m_el[p][p]) / (2 * mpq); + btScalar theta2 = theta * theta; + btScalar cos; + btScalar sin; + if (theta2 * theta2 < btScalar(10 / SIMD_EPSILON)) + { + t = (theta >= 0) ? 1 / (theta + btSqrt(1 + theta2)) + : 1 / (theta - btSqrt(1 + theta2)); + cos = 1 / btSqrt(1 + t * t); + sin = cos * t; + } + else + { + // approximation for large theta-value, i.e., a nearly diagonal matrix + t = 1 / (theta * (2 + btScalar(0.5) / theta2)); + cos = 1 - btScalar(0.5) * t * t; + sin = cos * t; + } + + // apply rotation to matrix (this = J^T * this * J) + m_el[p][q] = m_el[q][p] = 0; + m_el[p][p] -= t * mpq; + m_el[q][q] += t * mpq; + btScalar mrp = m_el[r][p]; + btScalar mrq = m_el[r][q]; + m_el[r][p] = m_el[p][r] = cos * mrp - sin * mrq; + m_el[r][q] = m_el[q][r] = cos * mrq + sin * mrp; + + // apply rotation to rot (rot = rot * J) + for (int i = 0; i < 3; i++) + { + btVector3& row = rot[i]; + mrp = row[p]; + mrq = row[q]; + row[p] = cos * mrp - sin * mrq; + row[q] = cos * mrq + sin * mrp; + } + } + } + + protected: btScalar cofac(int r1, int c1, int r2, int c2) const diff --git a/extern/bullet2/src/LinearMath/btScalar.h b/extern/bullet2/src/LinearMath/btScalar.h index 1fee626d0c0..3c96857d4eb 100644 --- a/extern/bullet2/src/LinearMath/btScalar.h +++ b/extern/bullet2/src/LinearMath/btScalar.h @@ -24,7 +24,7 @@ subject to the following restrictions: #include #include -#define BT_BULLET_VERSION 271 +#define BT_BULLET_VERSION 272 inline int btGetVersion() { @@ -65,7 +65,11 @@ inline int btGetVersion() #endif //__MINGW32__ #include +#if defined(DEBUG) || defined (_DEBUG) #define btAssert assert +#else + #define btAssert(x) +#endif //btFullAssert is optional, slows down a lot #define btFullAssert(x) @@ -116,7 +120,13 @@ inline int btGetVersion() #ifndef assert #include #endif + +#if defined(DEBUG) || defined (_DEBUG) #define btAssert assert +#else + #define btAssert(x) +#endif + //btFullAssert is optional, slows down a lot #define btFullAssert(x) #define btLikely(_c) _c @@ -145,11 +155,16 @@ typedef float btScalar; #endif + #define BT_DECLARE_ALIGNED_ALLOCATOR() \ - SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ - SIMD_FORCE_INLINE void operator delete(void* ptr) { btAlignedFree(ptr); } \ - SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \ - SIMD_FORCE_INLINE void operator delete(void*, void*) { } \ + SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ + SIMD_FORCE_INLINE void operator delete(void* ptr) { btAlignedFree(ptr); } \ + SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) { return ptr; } \ + SIMD_FORCE_INLINE void operator delete(void*, void*) { } \ + SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes) { return btAlignedAlloc(sizeInBytes,16); } \ + SIMD_FORCE_INLINE void operator delete[](void* ptr) { btAlignedFree(ptr); } \ + SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr) { return ptr; } \ + SIMD_FORCE_INLINE void operator delete[](void*, void*) { } \ diff --git a/extern/bullet2/src/btBulletCollisionCommon.h b/extern/bullet2/src/btBulletCollisionCommon.h index b21d8b4f66c..4b14f6d00f3 100644 --- a/extern/bullet2/src/btBulletCollisionCommon.h +++ b/extern/bullet2/src/btBulletCollisionCommon.h @@ -43,7 +43,9 @@ subject to the following restrictions: ///Narrowphase Collision Detector #include "BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h" -#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" + +//btSphereBoxCollisionAlgorithm is broken, use gjk for now +//#include "BulletCollision/CollisionDispatch/btSphereBoxCollisionAlgorithm.h" #include "BulletCollision/CollisionDispatch/btDefaultCollisionConfiguration.h" ///Dispatching and generation of collision pairs (broadphase) diff --git a/extern/bullet2/src/btBulletDynamicsCommon.h b/extern/bullet2/src/btBulletDynamicsCommon.h index ce9bb1d968b..b95972cd15d 100644 --- a/extern/bullet2/src/btBulletDynamicsCommon.h +++ b/extern/bullet2/src/btBulletDynamicsCommon.h @@ -32,9 +32,7 @@ subject to the following restrictions: #include "BulletDynamics/ConstraintSolver/btSliderConstraint.h" #include "BulletDynamics/ConstraintSolver/btSequentialImpulseConstraintSolver.h" -///Optional ODE quickstep constraint solver, redistributed under ZLib license -#include "BulletDynamics/ConstraintSolver/btOdeQuickstepConstraintSolver.h" -#include "BulletDynamics/ConstraintSolver/btOdeTypedJoint.h" + ///Vehicle simulation, with wheel contact simulated by raycasts #include "BulletDynamics/Vehicle/btRaycastVehicle.h" From 17478eeb234676a28b45729d29eeb15fb6ac0328 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sat, 13 Sep 2008 08:05:16 +0000 Subject: [PATCH 041/125] Update MSVC project file for latest Bullet revision. Remove compound patch as it is now included in Bullet trunk. --- extern/bullet2/bullet_compound_raycast.patch | 39 ------------------- .../bullet2/make/msvc_7_0/Bullet_vc7.vcproj | 39 ------------------- 2 files changed, 78 deletions(-) delete mode 100644 extern/bullet2/bullet_compound_raycast.patch diff --git a/extern/bullet2/bullet_compound_raycast.patch b/extern/bullet2/bullet_compound_raycast.patch deleted file mode 100644 index 2658f7ed56e..00000000000 --- a/extern/bullet2/bullet_compound_raycast.patch +++ /dev/null @@ -1,39 +0,0 @@ -Index: src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp -=================================================================== ---- src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp (r‚vision 16464) -+++ src/BulletCollision/CollisionDispatch/btCollisionWorld.cpp (copie de travail) -@@ -379,12 +379,16 @@ - btTransform childTrans = compoundShape->getChildTransform(i); - const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); - btTransform childWorldTrans = colObjWorldTransform * childTrans; -+ // replace collision shape so that callback can determine the triangle -+ btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape(); -+ collisionObject->setCollisionShape((btCollisionShape*)childCollisionShape); - rayTestSingle(rayFromTrans,rayToTrans, - collisionObject, - childCollisionShape, - childWorldTrans, - resultCallback); -- -+ // restore -+ collisionObject->setCollisionShape(saveCollisionShape); - } - } - } -@@ -571,11 +575,16 @@ - btTransform childTrans = compoundShape->getChildTransform(i); - const btCollisionShape* childCollisionShape = compoundShape->getChildShape(i); - btTransform childWorldTrans = colObjWorldTransform * childTrans; -+ // replace collision shape so that callback can determine the triangle -+ btCollisionShape* saveCollisionShape = collisionObject->getCollisionShape(); -+ collisionObject->setCollisionShape((btCollisionShape*)childCollisionShape); - objectQuerySingle(castShape, convexFromTrans,convexToTrans, - collisionObject, - childCollisionShape, - childWorldTrans, - resultCallback, allowedPenetration); -+ // restore -+ collisionObject->setCollisionShape(saveCollisionShape); - } - } - } diff --git a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj index 225a6ead3be..186b03ad67d 100644 --- a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj +++ b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj @@ -382,36 +382,6 @@ ECHO Done - - - - - - - - - - - - - - - - - - - - @@ -442,12 +412,6 @@ ECHO Done - - - - @@ -1057,9 +1021,6 @@ ECHO Done - - From 9a94620df04dfc7b62da6022b91cda03118cdf5f Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sat, 13 Sep 2008 08:10:50 +0000 Subject: [PATCH 042/125] Adapt MSVC project files for latest lib/windows configuration (update lib/windows first). --- projectfiles_vc7/blender/blender.vcproj | 6 +++--- projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj | 2 +- .../gameengine/gameplayer/ghost/GP_ghost.vcproj | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/projectfiles_vc7/blender/blender.vcproj b/projectfiles_vc7/blender/blender.vcproj index 4eda818dad7..26cb3fb79e1 100644 --- a/projectfiles_vc7/blender/blender.vcproj +++ b/projectfiles_vc7/blender/blender.vcproj @@ -60,7 +60,7 @@ MOVE /Y ..\..\bin\blender.lib ..\..\..\build\msvc_7\libs MOVE /Y ..\..\bin\blender.exp ..\..\..\build\msvc_7\libs ECHO Copying required 3rd party dlls... -XCOPY /Y ..\..\..\lib\windows\python\lib\python25.dll ..\..\bin +XCOPY /Y ..\..\..\lib\windows\python\lib\lib25_vs2003\python25.dll ..\..\bin XCOPY /Y ..\..\..\lib\windows\gettext\lib\*.dll ..\..\bin XCOPY /Y ..\..\..\lib\windows\sdl\lib\*.dll ..\..\bin XCOPY /Y ..\..\..\lib\windows\tiff\lib\*.dll ..\..\bin @@ -129,7 +129,7 @@ ECHO Done OutputFile="..\..\bin\debug\blender.exe" LinkIncremental="2" SuppressStartupBanner="TRUE" - AdditionalLibraryDirectories="..\..\..\lib\windows\sdl\lib;..\..\..\lib\windows\ode\lib;..\..\..\lib\windows\zlib\lib;..\..\..\lib\windows\png\lib;..\..\..\lib\windows\jpeg\lib;..\..\..\lib\windows\pthreads\lib;..\..\..\lib\windows\tiff\lib;..\..\..\lib\windows\gettext\lib;..\..\..\lib\windows\freetype\lib;..\..\..\lib\windows\python\lib;..\..\..\lib\windows\openal\lib;..\..\..\lib\windows\openexr\lib;..\..\..\lib\windows\QTDevWin\Libraries;..\..\..\lib\windows\ffmpeg\lib;..\..\..\build\msvc_7\libs\intern\debug;..\..\..\build\msvc_7\libs\extern\debug" + AdditionalLibraryDirectories="..\..\..\lib\windows\sdl\lib;..\..\..\lib\windows\ode\lib;..\..\..\lib\windows\zlib\lib;..\..\..\lib\windows\png\lib;..\..\..\lib\windows\jpeg\lib;..\..\..\lib\windows\pthreads\lib;..\..\..\lib\windows\tiff\lib;..\..\..\lib\windows\gettext\lib;..\..\..\lib\windows\freetype\lib;..\..\..\lib\windows\python\lib\lib25_vs2003;..\..\..\lib\windows\openal\lib;..\..\..\lib\windows\openexr\lib;..\..\..\lib\windows\QTDevWin\Libraries;..\..\..\lib\windows\ffmpeg\lib;..\..\..\build\msvc_7\libs\intern\debug;..\..\..\build\msvc_7\libs\extern\debug" IgnoreDefaultLibraryNames="libc.lib, libcmt.lib, msvcrt.lib, libcd.lib, odbc32.lib, odbccp32.lib" GenerateDebugInformation="TRUE" ProgramDatabaseFile="..\..\..\build\msvc_7\libs\debug\blender.pdb" @@ -146,7 +146,7 @@ MOVE /Y ..\..\bin\debug\blender.ilk ..\..\..\build\msvc_7\libs\debug ECHO Copying required 3rd party dlls... XCOPY /Y ..\..\..\lib\windows\gettext\lib\*.dll ..\..\bin\debug XCOPY /Y ..\..\..\lib\windows\sdl\lib\*.dll ..\..\bin\debug -XCOPY /Y ..\..\..\lib\windows\python\lib\python25_d.dll ..\..\bin\debug +XCOPY /Y ..\..\..\lib\windows\python\lib\lib25_vs2003\python25_d.dll ..\..\bin\debug XCOPY /Y ..\..\..\lib\windows\CRTL\lib\msvcrtd.dll ..\..\bin\debug XCOPY /Y ..\..\..\lib\windows\tiff\lib\*.dll ..\..\bin\debug XCOPY /Y ..\..\..\lib\windows\pthreads\lib\pthreadVSE2.dll ..\..\bin\debug diff --git a/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj b/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj index 14c534adeec..69ead7fd9cb 100644 --- a/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj +++ b/projectfiles_vc7/blender/blenkernel/BKE_blenkernel.vcproj @@ -74,7 +74,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories="..\..\..\..\lib\windows\python\include\python2.5;..\..\..\..\lib\windows\zlib\include;..\..\..\..\lib\windows\sdl\include;..\..\..\..\lib\windows\ffmpeg\include;..\..\..\..\build\msvc_7\intern\bmfont\include;..\..\..\..\build\msvc_7\intern\bsp\include;..\..\..\..\build\msvc_7\intern\guardedalloc\include;..\..\..\..\build\msvc_7\intern\decimation\include;..\..\..\..\build\msvc_7\intern\elbeem\include;..\..\..\..\build\msvc_7\intern\iksolver\include;..\..\..\source\blender;..\..\..\source\blender\avi;..\..\..\source\blender\imbuf;..\..\..\source\blender\include;..\..\..\source\blender\python;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\makesdna;..\..\..\source\blender\nodes;..\..\..\source\blender\blenloader;..\..\..\source\kernel\gen_system;..\..\..\source\blender\renderconverter;..\..\..\source\blender\render\extern\include;..\..\..\source\gameengine\SoundSystem;..\..\..\..\build\msvc_7\extern\verse\include;..\..\..\..\build\msvc_7\intern\opennl\include;..\..\..\..\build\msvc_7\extern\bullet\include;..\..\..\..\build\msvc_7\extern\glew\include;..\..\..\source\blender\gpu" - PreprocessorDefinitions="_DEBUG;WIN32;_LIB;WITH_FREETYPE2;WITH_VERSE;WITH_OPENEXR;WITH_DDS;WITH_BULLET = 1;WITH_FFMPEG" + PreprocessorDefinitions="_DEBUG;WIN32;_LIB;WITH_FREETYPE2;WITH_VERSE;WITH_OPENEXR;WITH_DDS;WITH_BULLET;WITH_FFMPEG" BasicRuntimeChecks="3" RuntimeLibrary="1" DefaultCharIsUnsigned="TRUE" diff --git a/projectfiles_vc7/gameengine/gameplayer/ghost/GP_ghost.vcproj b/projectfiles_vc7/gameengine/gameplayer/ghost/GP_ghost.vcproj index 8f79250d1ea..1dbe144f74d 100644 --- a/projectfiles_vc7/gameengine/gameplayer/ghost/GP_ghost.vcproj +++ b/projectfiles_vc7/gameengine/gameplayer/ghost/GP_ghost.vcproj @@ -60,7 +60,7 @@ MOVE /Y ..\..\..\..\bin\debug\blenderplayer.lib ..\..\..\..\..\build\msvc_7\libs MOVE /Y ..\..\..\..\bin\debug\blenderplayer.exp ..\..\..\..\..\build\msvc_7\libs\debug MOVE /Y ..\..\..\..\bin\debug\blenderplayer.ilk ..\..\..\..\..\build\msvc_7\libs\debug ECHO Copying required 3rd party dlls... -XCOPY /Y ..\..\..\..\..\lib\windows\python\lib\python25_d.dll ..\..\..\..\bin\debug +XCOPY /Y ..\..\..\..\..\lib\windows\python\lib\lib25_vs2003\python25_d.dll ..\..\..\..\bin\debug XCOPY /Y ..\..\..\..\..\lib\windows\sdl\lib\SDL.dll ..\..\..\..\bin\debug XCOPY /Y ..\..\..\..\..\lib\windows\png\lib\libpng.dll ..\..\..\..\bin\debug XCOPY /Y ..\..\..\..\..\lib\windows\zlib\lib\zlib.dll ..\..\..\..\bin\debug @@ -134,7 +134,7 @@ ECHO Done MOVE /Y ..\..\..\..\bin\blenderplayer.lib ..\..\..\..\..\build\msvc_7\libs MOVE /Y ..\..\..\..\bin\blenderplayer.exp ..\..\..\..\..\build\msvc_7\libs ECHO Copying required 3rd party dlls... -XCOPY /Y ..\..\..\..\..\lib\windows\python\lib\python25.dll ..\..\..\..\bin +XCOPY /Y ..\..\..\..\..\lib\windows\python\lib\lib25_vs2003\python25.dll ..\..\..\..\bin XCOPY /Y ..\..\..\..\..\lib\windows\sdl\lib\SDL.dll ..\..\..\..\bin XCOPY /Y ..\..\..\..\..\lib\windows\png\lib\libpng.dll ..\..\..\..\bin XCOPY /Y ..\..\..\..\..\lib\windows\zlib\lib\zlib.dll ..\..\..\..\bin From 1c3043f011f8e08ff1c4a3fbf438b676259e1c34 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 13 Sep 2008 08:22:55 +0000 Subject: [PATCH 043/125] 32 sounds max would crash on windows because the openal limit is 24, tested an the to-frankie demo playes ok with 24, but would be good to make use of the sound lib's 'priority' option. --- intern/SoundSystem/SoundDefines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/SoundSystem/SoundDefines.h b/intern/SoundSystem/SoundDefines.h index 9758fdaadea..450fde187b5 100644 --- a/intern/SoundSystem/SoundDefines.h +++ b/intern/SoundSystem/SoundDefines.h @@ -44,7 +44,7 @@ enum /* general stuff */ #define NUM_BUFFERS 128 -#define NUM_SOURCES 32 +#define NUM_SOURCES 24 /* 24 is the limit for openal on windows, was 16 in 2.47 and previous */ /* openal related stuff */ #define AL_LOOPING 0x1007 From a9a8f74b805410c0ebb3c6fc59dcde6d726100e7 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sat, 13 Sep 2008 11:41:52 +0000 Subject: [PATCH 044/125] Update MSVC project files for latest bullet revision --- extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj index 186b03ad67d..7a6b58b2ed7 100644 --- a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj +++ b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj @@ -878,6 +878,12 @@ ECHO Done + + + + From dfb5ebb12ea18bc8982777142c6e185cb389ad45 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 13 Sep 2008 11:43:01 +0000 Subject: [PATCH 045/125] return dummy python values when no joystick is present --- .../GameLogic/SCA_JoystickSensor.cpp | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 8ef33240592..3c08710c6ce 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -402,7 +402,8 @@ PyObject* SCA_JoystickSensor::PyGetRealAxis( PyObject* self) { SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); if(joy) return Py_BuildValue("[iiii]", joy->GetAxis10(), joy->GetAxis11(), joy->GetAxis20(), joy->GetAxis21()); - return NULL; + else + return Py_BuildValue("[iiii]", 0, 0, 0, 0); } @@ -483,9 +484,8 @@ char SCA_JoystickSensor::NumberOfAxes_doc[] = "\tReturns the number of axes .\n"; PyObject* SCA_JoystickSensor::PyNumberOfAxes( PyObject* self ) { SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - if(joy) - return PyInt_FromLong( joy->GetNumberOfAxes() ); - return false; + // when the joystick is null their is 0 exis still. dumb but scripters should use isConnected() + return PyInt_FromLong( joy ? joy->GetNumberOfAxes() : 0 ); } @@ -494,9 +494,7 @@ char SCA_JoystickSensor::NumberOfButtons_doc[] = "\tReturns the number of buttons .\n"; PyObject* SCA_JoystickSensor::PyNumberOfButtons( PyObject* self ) { SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - if(joy) - return PyInt_FromLong( joy->GetNumberOfButtons() ); - return false; + return PyInt_FromLong( joy ? joy->GetNumberOfButtons() : 0 ); } @@ -505,9 +503,7 @@ char SCA_JoystickSensor::NumberOfHats_doc[] = "\tReturns the number of hats .\n"; PyObject* SCA_JoystickSensor::PyNumberOfHats( PyObject* self ) { SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - if(joy) - return PyInt_FromLong( joy->GetNumberOfHats() ); - return false; + return PyInt_FromLong( joy ? joy->GetNumberOfHats() : 0 ); } char SCA_JoystickSensor::Connected_doc[] = @@ -515,7 +511,5 @@ char SCA_JoystickSensor::Connected_doc[] = "\tReturns True if a joystick is connected at this joysticks index.\n"; PyObject* SCA_JoystickSensor::PyConnected( PyObject* self ) { SCA_Joystick *joy = m_pJoystickMgr->GetJoystickDevice(m_joyindex); - if(joy) - return PyBool_FromLong( joy->Connected() ); - return false; + return PyBool_FromLong( joy ? joy->Connected() : 0 ); } From ba9d3aa4ab1be8c7faa28c9d49b4d0ed5f17b32a Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sat, 13 Sep 2008 11:46:07 +0000 Subject: [PATCH 046/125] BGE patch: fix transform bug on compound shape: child shape didn't take into account parent inverse node. Fix scaling bug on instantiation of compound shape: child shape didn't have correct shape. Note: global scaling doesn't work on compound shape (limitation of Bullet); don't set any scale on the top dynamic object. --- .../Ketsji/KX_ConvertPhysicsObjects.cpp | 26 ++++++++++++++++--- .../Physics/Bullet/CcdPhysicsController.cpp | 1 + .../Physics/Bullet/CcdPhysicsController.h | 2 ++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 9607489497d..6507bf501e4 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -801,11 +801,29 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, assert(colShape->isCompound()); btCompoundShape* compoundShape = (btCompoundShape*)colShape; - MT_Point3 childPos = gameobj->GetSGNode()->GetLocalPosition(); - MT_Matrix3x3 childRot = gameobj->GetSGNode()->GetLocalOrientation(); - MT_Vector3 childScale = gameobj->GetSGNode()->GetLocalScale(); + // compute the local transform from parent, this may include a parent inverse node + SG_Node* gameNode = gameobj->GetSGNode(); + SG_Node* parentInverseNode = gameNode->GetSGParent(); + if (parentInverseNode && parentInverseNode->GetSGClientObject() != NULL) + // this is not a parent inverse node, cancel it + parentInverseNode = NULL; + // now combine the parent inverse node and the game node + MT_Point3 childPos = gameNode->GetLocalPosition(); + MT_Matrix3x3 childRot = gameNode->GetLocalOrientation(); + MT_Vector3 childScale = gameNode->GetLocalScale(); + if (parentInverseNode) + { + const MT_Point3& parentInversePos = parentInverseNode->GetLocalPosition(); + const MT_Matrix3x3& parentInverseRot = parentInverseNode->GetLocalOrientation(); + const MT_Vector3& parentInverseScale = parentInverseNode->GetLocalScale(); + childRot = parentInverseRot * childRot; + childScale = parentInverseScale * childScale; + childPos = parentInversePos+parentInverseScale*(parentInverseRot*childPos); + } - bm->setLocalScaling(btVector3(childScale.x(),childScale.y(),childScale.z())); + shapeInfo->m_childScale.setValue(childScale.x(),childScale.y(),childScale.z()); + bm->setLocalScaling(shapeInfo->m_childScale); + shapeInfo->m_childTrans.setOrigin(btVector3(childPos.x(),childPos.y(),childPos.z())); float rotval[12]; childRot.getValue(rotval); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index b67cf0425c5..b9266bb9b0e 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -924,6 +924,7 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() collisionShape = nextShapeInfo->CreateBulletShape(); if (collisionShape) { + collisionShape->setLocalScaling(nextShapeInfo->m_childScale); compoundShape->addChildShape(nextShapeInfo->m_childTrans, collisionShape); } } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index a3fbb502c08..d6f0867e01d 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -47,6 +47,7 @@ public: m_radius(1.0), m_height(1.0), m_halfExtend(0.f,0.f,0.f), + m_childScale(1.0f,1.0f,1.0f), m_nextShape(NULL), m_refCount(1) { @@ -96,6 +97,7 @@ public: btScalar m_height; btVector3 m_halfExtend; btTransform m_childTrans; + btVector3 m_childScale; std::vector m_vertexArray; // Contains both vertex array for polytope shape and // triangle array for concave mesh shape. // In this case a triangle is made of 3 consecutive points From ce41cfa40a1c5db8b8091f64ab0d6f3b5d116cde Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 13 Sep 2008 12:07:36 +0000 Subject: [PATCH 047/125] bullet wasnt building on 64bit linux --- .../CollisionDispatch/btCompoundCollisionAlgorithm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp index da9336c55c7..57812818007 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp @@ -141,7 +141,7 @@ public: } void Process(const btDbvtNode* leaf) { - int index = int(leaf->data); + int index = int(long(leaf->data)); btCompoundShape* compoundShape = static_cast(m_compoundColObj->getCollisionShape()); btCollisionShape* childShape = compoundShape->getChildShape(index); From 63ecf9966ec98ba9135a0229b4601e25c60d53b0 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 13 Sep 2008 14:21:06 +0000 Subject: [PATCH 048/125] Fix to make blenderplayer compile with makefiles on Mac OS X. It worked on Linux already, I think there is a difference in the linker. --- source/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/source/Makefile b/source/Makefile index aebeb8f30c2..37833a5829c 100644 --- a/source/Makefile +++ b/source/Makefile @@ -242,6 +242,7 @@ endif SPLIB1 = $(OCGDIR)/gameengine/GamePlayer/ghost/$(DEBUG_DIR)libghost.a SPLIB1 += $(OCGDIR)/gameengine/GamePlayer/common/$(DEBUG_DIR)libcommon.a +SPLIB1 += $(OCGDIR)/gameengine/blconverter/$(DEBUG_DIR)libblconverter.a SPLIB1 += $(NAN_STRING)/lib/$(DEBUG_DIR)libstring.a SPLIB1 += $(NAN_GHOST)/lib/$(DEBUG_DIR)libghost.a From 8925ae60428ed213fd8cb1271671e6ca56fda70e Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sat, 13 Sep 2008 16:03:11 +0000 Subject: [PATCH 049/125] BGE patch: use new btScaledBvhTriangleMeshShape to allow shape sharing between replicas and avoid BVH rebuild in case of scaling. This will save memory and speed up greatly the instantiation of static mesh. --- .../Physics/Bullet/CcdPhysicsController.cpp | 32 ++++++--- .../Physics/Bullet/CcdPhysicsController.h | 7 ++ .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 72 ++++++++++--------- 3 files changed, 68 insertions(+), 43 deletions(-) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index b9266bb9b0e..4da9143fc3d 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -15,7 +15,7 @@ subject to the following restrictions: #include "CcdPhysicsController.h" #include "btBulletDynamicsCommon.h" - +#include "BulletCollision/CollisionShapes/btScaledBvhTriangleMeshShape.h" #include "PHY_IMotionState.h" #include "CcdPhysicsEnvironment.h" #include "RAS_MeshObject.h" @@ -904,15 +904,26 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() break; case PHY_SHAPE_MESH: - collisionMeshData = new btTriangleMesh(); - // m_vertexArray is necessarily a multiple of 3 - for (std::vector::iterator it=m_vertexArray.begin(); it != m_vertexArray.end(); ) + // Let's use the latest btScaledBvhTriangleMeshShape: it allows true sharing of + // triangle mesh information between duplicates => drastic performance increase when + // duplicating complex mesh objects. + // BUT it causes a small performance decrease when sharing is not required: + // 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) { - 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(); } - concaveShape = new btBvhTriangleMeshShape( collisionMeshData, true ); - concaveShape->recalcLocalAabb(); - collisionShape = concaveShape; + collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f)); break; case PHY_SHAPE_COMPOUND: @@ -953,7 +964,10 @@ CcdShapeConstructionInfo::~CcdShapeConstructionInfo() childShape->Release(); childShape = nextShape; } - + if (m_unscaledShape) + { + DeleteBulletShape(m_unscaledShape); + } m_vertexArray.clear(); } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index d6f0867e01d..a685c466944 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -49,6 +49,7 @@ public: m_halfExtend(0.f,0.f,0.f), m_childScale(1.0f,1.0f,1.0f), m_nextShape(NULL), + m_unscaledShape(NULL), m_refCount(1) { m_childTrans.setIdentity(); @@ -72,6 +73,10 @@ public: void AddShape(CcdShapeConstructionInfo* shapeInfo); + btTriangleMeshShape* GetMeshShape(void) + { + return m_unscaledShape; + } CcdShapeConstructionInfo* GetNextShape() { return m_nextShape; @@ -108,6 +113,8 @@ public: protected: CcdShapeConstructionInfo* m_nextShape; // for compound shape + btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape, + // the actual shape is of type btScaledBvhTriangleMeshShape int m_refCount; // this class is shared between replicas // keep track of users so that we can release it }; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 6df3297ec7e..5042df2162a 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -816,44 +816,48 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac // If the user requests the real normal, compute it now if (filterCallback.m_faceNormal) { - // this code is copied from Bullet - btVector3 triangle[3]; - const unsigned char *vertexbase; - int numverts; - PHY_ScalarType type; - int stride; - const unsigned char *indexbase; - int indexstride; - int numfaces; - PHY_ScalarType indicestype; - btTriangleMeshShape* triangleShape = (btTriangleMeshShape*)shape; - btStridingMeshInterface* meshInterface = triangleShape->getMeshInterface(); - - meshInterface->getLockedReadOnlyVertexIndexBase( - &vertexbase, - numverts, - type, - stride, - &indexbase, - indexstride, - numfaces, - indicestype, - 0); - - unsigned int* gfxbase = (unsigned int*)(indexbase+rayCallback.m_hitTriangleIndex*indexstride); - const btVector3& meshScaling = meshInterface->getScaling(); - for (int j=2;j>=0;j--) + // mesh shapes are shared and stored in the shapeInfo + btTriangleMeshShape* triangleShape = shapeInfo->GetMeshShape(); + if (triangleShape) { - int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + // this code is copied from Bullet + btVector3 triangle[3]; + const unsigned char *vertexbase; + int numverts; + PHY_ScalarType type; + int stride; + const unsigned char *indexbase; + int indexstride; + int numfaces; + PHY_ScalarType indicestype; + btStridingMeshInterface* meshInterface = triangleShape->getMeshInterface(); - btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); + meshInterface->getLockedReadOnlyVertexIndexBase( + &vertexbase, + numverts, + type, + stride, + &indexbase, + indexstride, + numfaces, + indicestype, + 0); - triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + unsigned int* gfxbase = (unsigned int*)(indexbase+rayCallback.m_hitTriangleIndex*indexstride); + const btVector3& meshScaling = shape->getLocalScaling(); + for (int j=2;j>=0;j--) + { + int graphicsindex = indicestype==PHY_SHORT?((unsigned short*)gfxbase)[j]:gfxbase[j]; + + btScalar* graphicsbase = (btScalar*)(vertexbase+graphicsindex*stride); + + triangle[j] = btVector3(graphicsbase[0]*meshScaling.getX(),graphicsbase[1]*meshScaling.getY(),graphicsbase[2]*meshScaling.getZ()); + } + meshInterface->unLockReadOnlyVertexBase(0); + btVector3 triangleNormal; + triangleNormal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]); + rayCallback.m_hitNormalWorld = rayCallback.m_collisionObject->getWorldTransform().getBasis()*triangleNormal; } - meshInterface->unLockReadOnlyVertexBase(0); - btVector3 triangleNormal; - triangleNormal = (triangle[1]-triangle[0]).cross(triangle[2]-triangle[0]); - rayCallback.m_hitNormalWorld = rayCallback.m_collisionObject->getWorldTransform().getBasis()*triangleNormal; } } } From d2186508da224805db8d2fe299738a94e1a5e750 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Sat, 13 Sep 2008 18:09:41 +0000 Subject: [PATCH 050/125] Particle collisions upgrade: - Particle now use the deflector objects collision modifier data to collide with deflectors and as a result can now use the velocity of the colliding object for more realistic collisions. - Dynamic rotations are also quite a bit more realistic and are related to the friction setting of the deflector (to get any dynamic rotations there has to be some friction). This is largely due to the separate handling of rolling friction (approximated to be 1% of normal sliding friction). - Collisions should be a bit faster on complex deflectors due to the tree structure used by the collision modifier. - Collision should also generally be a bit more accurate. To be noted: Only the average velocity of individual deflector faces is used, so collisions with rotating or deforming objects can't be handled accurately - this would require much more complex calculations. Subdividing the deflector object surface to smaller faces can help with this as the individual face velocities become more linear. --- source/blender/blenkernel/intern/effect.c | 2 +- .../blenkernel/intern/particle_system.c | 600 ++++++++---------- source/blender/blenkernel/intern/shrinkwrap.c | 2 +- source/blender/blenlib/BLI_kdopbvh.h | 3 +- source/blender/blenlib/intern/BLI_kdopbvh.c | 11 +- source/blender/makesdna/DNA_particle_types.h | 1 + 6 files changed, 270 insertions(+), 349 deletions(-) diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 72f70cf17ff..327008c60de 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -267,7 +267,7 @@ static float eff_calc_visibility(Object *ob, float *co, float *dir) hit.dist = len + FLT_EPSILON; // check if the way is blocked - if(BLI_bvhtree_ray_cast(collmd->bvhtree, co, norm, &hit, eff_tri_ray_hit, NULL)>=0) + if(BLI_bvhtree_ray_cast(collmd->bvhtree, co, norm, 0.0f, &hit, eff_tri_ray_hit, NULL)>=0) { // visibility is only between 0 and 1, calculated from 1-absorption visibility *= MAX2(0.0, MIN2(1.0, (1.0-((float)collmd->absorption)*0.01))); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 3f5911b896b..bac92af5bee 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -53,12 +53,14 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" #include "BLI_kdtree.h" +#include "BLI_kdopbvh.h" #include "BLI_linklist.h" #include "BLI_threads.h" #include "BKE_anim.h" #include "BKE_bad_level_calls.h" #include "BKE_cdderivedmesh.h" +#include "BKE_collision.h" #include "BKE_displist.h" #include "BKE_effect.h" #include "BKE_particle.h" @@ -2432,7 +2434,7 @@ void psys_end_effectors(ParticleSystem *psys) } } -static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd) +static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra) { ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; @@ -2472,96 +2474,20 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo } } } - else if(ec->type==PSYS_EC_DEFLECT){ - DerivedMesh *dm; - MFace *mface=0; - MVert *mvert=0; - int i, totface; - float v1[3],v2[3],v3[3],v4[4], *min, *max; - - if(ob==ec->ob) - dm=psmd->dm; - else{ - psys_disable_all(ec->ob); - - dm=mesh_get_derived_final(ec->ob,0); - - psys_enable_all(ec->ob); - } - - if(dm){ - totvert=dm->getNumVerts(dm); - totface=dm->getNumFaces(dm); - mface=dm->getFaceDataArray(dm,CD_MFACE); - mvert=dm->getVertDataArray(dm,CD_MVERT); - - /* Decide which is faster to calculate by the amount of*/ - /* matrice multiplications needed to convert spaces. */ - /* With size deflect we have to convert allways because */ - /* the object can be scaled nonuniformly (sphere->ellipsoid). */ - if(totvert<2*psys->totpart || part->flag & PART_SIZE_DEFL){ - co=ec->vert_cos=MEM_callocN(sizeof(float)*3*totvert,"Particle deflection vert cos"); - /* convert vert coordinates to global (particle) coordinates */ - for(i=0; iob->obmat,co); - } - co=ec->vert_cos; - } - else - ec->vert_cos=0; - - INIT_MINMAX(ec->ob_minmax,ec->ob_minmax+3); - - min=ec->face_minmax=MEM_callocN(sizeof(float)*6*totface,"Particle deflection face minmax"); - max=min+3; - - for(i=0; iv1); - VECCOPY(v2,co+3*mface->v2); - VECCOPY(v3,co+3*mface->v3); - } - else{ - VECCOPY(v1,mvert[mface->v1].co); - VECCOPY(v2,mvert[mface->v2].co); - VECCOPY(v3,mvert[mface->v3].co); - } - INIT_MINMAX(min,max); - DO_MINMAX(v1,min,max); - DO_MINMAX(v2,min,max); - DO_MINMAX(v3,min,max); - - if(mface->v4){ - if(co){ - VECCOPY(v4,co+3*mface->v4); - } - else{ - VECCOPY(v4,mvert[mface->v4].co); - } - DO_MINMAX(v4,min,max); - } - - DO_MINMAX(min,ec->ob_minmax,ec->ob_minmax+3); - DO_MINMAX(max,ec->ob_minmax,ec->ob_minmax+3); - } - } - else - ec->face_minmax=0; - } else if(ec->type==PSYS_EC_PARTICLE){ + 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; + if(psys->part->phystype==PART_PHYS_BOIDS){ - Object *eob = ec->ob; - ParticleSystem *epsys; - ParticleSettings *epart; ParticleData *epa; ParticleKey state; PartDeflect *pd; - int totepart, p; - epsys= BLI_findlink(&eob->particlesystem,ec->psys_nbr); - epart= epsys->part; + int p; + pd= epart->pd; - totepart= epsys->totpart; if(pd->forcefield==PFIELD_FORCE && totepart){ KDTree *tree; @@ -2576,6 +2502,11 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo } } } + else if(ec->type==PSYS_EC_DEFLECT) { + CollisionModifierData *collmd = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) ); + if(collmd) + collision_move_object(collmd, 1.0, 0.0); + } } } @@ -3024,37 +2955,124 @@ int psys_intersect_dm(Object *ob, DerivedMesh *dm, float *vert_cos, float *co1, } return intersect; } + +/* container for moving data between deflet_particle and particle_intersect_face */ +typedef struct ParticleCollision +{ + struct Object *ob, *ob_t; // collided and current objects + struct CollisionModifierData *md; // collision modifier for ob_t; + float nor[3]; // normal at collision point + float vel[3]; // velocity of collision point + float co1[3], co2[3]; // ray start and end points + float ray_len; // original length of co2-co1, needed for collision time evaluation + float t; // time of previous collision, needed for substracting face velocity +} +ParticleCollision; + +static void particle_intersect_face(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) +{ + ParticleCollision *col = (ParticleCollision *) userdata; + MFace *face = col->md->mfaces + index; + MVert *x = col->md->x; + MVert *v = col->md->current_v; + float dir[3], vel[3], co1[3], co2[3], uv[2], ipoint[3], temp[3], dist, t, threshold; + int ret=0; + + float *t0, *t1, *t2, *t3; + t0 = x[ face->v1 ].co; + t1 = x[ face->v2 ].co; + t2 = x[ face->v3 ].co; + t3 = face->v4 ? x[ face->v4].co : NULL; + + /* calculate average velocity of face */ + VECCOPY(vel, v[ face->v1 ].co); + VECADD(vel, vel, v[ face->v2 ].co); + VECADD(vel, vel, v[ face->v3 ].co); + VecMulf(vel, 0.33334f); + + /* substract face velocity, in other words convert to + a coordinate system where only the particle moves */ + VECADDFAC(co1, col->co1, vel, -col->t); + VECSUB(co2, col->co2, vel); + + do + { + if(ray->radius == 0.0f) { + if(LineIntersectsTriangle(co1, co2, t0, t1, t2, &t, uv)) { + if(t >= 0.0f && t < hit->dist/col->ray_len) { + hit->dist = col->ray_len * t; + hit->index = index; + + /* calculate normal that's facing the particle */ + CalcNormFloat(t0, t1, t2, col->nor); + VECSUB(temp, co2, co1); + if(Inpf(col->nor, temp) > 0.0f) + VecMulf(col->nor, -1.0f); + + VECCOPY(col->vel,vel); + + col->ob = col->ob_t; + } + } + } + else { + if(SweepingSphereIntersectsTriangleUV(co1, co2, ray->radius, t0, t1, t2, &t, ipoint)) { + if(t >=0.0f && t < hit->dist/col->ray_len) { + hit->dist = col->ray_len * t; + hit->index = index; + + VecLerpf(temp, co1, co2, t); + + VECSUB(col->nor, temp, ipoint); + Normalize(col->nor); + + VECCOPY(col->vel,vel); + + col->ob = col->ob_t; + } + } + } + + t1 = t2; + t2 = t3; + t3 = NULL; + + } while(t2); +} /* particle - mesh collision code */ /* in addition to basic point to surface collisions handles friction & damping,*/ /* 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 dfra, float cfra, ParticleKey *state, int *pa_die){ - Object *ob, *min_ob; - MFace *mface; - MVert *mvert; - DerivedMesh *dm; +static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float timestep, float dfra, float cfra, ParticleKey *state){ + Object *ob; ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; - ParticleKey cstate; - float imat[4][4]; - float co1[3],co2[3],def_loc[3],def_nor[3],unit_nor[3],def_tan[3],dvec[3],def_vel[3],dave[3],dvel[3]; - float pa_minmax[6]; - float min_w[4], zerovec[3]={0.0,0.0,0.0}, ipoint[3]; - float min_d,dotprod,damp,frict,o_len,d_len,radius=-1.0f; - int min_face=0, intersect=1, through=0; - short deflections=0, global=0; + ParticleKey reaction_state; + ParticleCollision col; + CollisionModifierData *collmd; + BVHTreeRayHit hit; + float ray_dir[3], zerovec[3]={0.0,0.0,0.0}; + float radius = ((part->flag & PART_SIZE_DEFL)?pa->size:0.0f); + int deflections=0, max_deflections=10; - VECCOPY(def_loc,pa->state.co); - VECCOPY(def_vel,pa->state.vel); + VECCOPY(col.co1, pa->state.co); + VECCOPY(col.co2, state->co); + col.t = 0.0f; /* 10 iterations to catch multiple deflections */ - if(lb->first) while(deflections<10){ - intersect=0; - global=0; - min_d=20000.0; - min_ob=NULL; + if(lb->first) while(deflections < max_deflections){ /* 1. */ + + VECSUB(ray_dir, col.co2, col.co1); + hit.index = -1; + hit.dist = col.ray_len = VecLength(ray_dir); + + /* even if particle is stationary we want to check for moving colliders */ + /* if hit.dist is zero the bvhtree_ray_cast will just ignore everything */ + if(hit.dist == 0.0f) + hit.dist = col.ray_len = 0.000001f; + for(ec=lb->first; ec; ec=ec->next){ if(ec->type & PSYS_EC_DEFLECT){ ob= ec->ob; @@ -3062,263 +3080,165 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part if(part->type!=PART_HAIR) where_is_object_time(ob,cfra); - if(ob==pob){ - dm=psmd->dm; - /* particles should not collide with emitter at birth */ - if(pa->time < cfra && pa->time >= psys->cfra) - continue; - } - else - dm=0; - - VECCOPY(co1,def_loc); - VECCOPY(co2,state->co); + /* particles should not collide with emitter at birth */ + if(ob==pob && pa->time < cfra && pa->time >= psys->cfra) + continue; - if(ec->vert_cos==0){ - /* convert particle coordinates to object coordinates */ - Mat4Invert(imat,ob->obmat); - Mat4MulVecfl(imat,co1); - Mat4MulVecfl(imat,co2); - } + col.md = ( CollisionModifierData * ) ( modifiers_findByType ( ec->ob, eModifierType_Collision ) ); + col.ob_t = ob; - INIT_MINMAX(pa_minmax,pa_minmax+3); - DO_MINMAX(co1,pa_minmax,pa_minmax+3); - DO_MINMAX(co2,pa_minmax,pa_minmax+3); - if(part->flag&PART_SIZE_DEFL){ - pa_minmax[0]-=pa->size; - pa_minmax[1]-=pa->size; - pa_minmax[2]-=pa->size; - pa_minmax[3]+=pa->size; - pa_minmax[4]+=pa->size; - pa_minmax[5]+=pa->size; - - radius=pa->size; - } - - if(ec->face_minmax==0 || AabbIntersectAabb(pa_minmax,pa_minmax+3,ec->ob_minmax,ec->ob_minmax+3)) { - if(psys_intersect_dm(ob,dm,ec->vert_cos,co1,co2,&min_d,&min_face,min_w, - ec->face_minmax,pa_minmax,radius,ipoint)){ - - min_ob=ob; - - if(ec->vert_cos) - global=1; - else - global=0; - } - } + if(col.md->bvhtree) + BLI_bvhtree_ray_cast(col.md->bvhtree, col.co1, ray_dir, radius, &hit, particle_intersect_face, &col); } } /* 2. */ - if(min_ob){ - BLI_srandom((int)cfra+p); - ob=min_ob; + if(hit.index>=0) { + PartDeflect *pd = col.ob->pd; + int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; + float co[3]; /* point of collision */ + float vec[3]; /* movement through collision */ + float vel[3]; /* velocity after collision */ + float t = hit.dist/col.ray_len; /* time of collision between this iteration */ + float dt = col.t + t * (1.0f - col.t); /* time of collision between frame change*/ - if(ob==pob){ - dm=psmd->dm; - } - else{ - psys_disable_all(ob); + VecLerpf(co, col.co1, col.co2, t); + VECSUB(vec, col.co2, col.co1); - dm=mesh_get_derived_final(ob,0); + VecMulf(col.vel, 1.0f-col.t); - psys_enable_all(ob); - } - - mface=dm->getFaceDataArray(dm,CD_MFACE); - mface+=min_face; - mvert=dm->getVertDataArray(dm,CD_MVERT); - - /* permeability check */ - if(BLI_frand()pd->pdef_perm) - through=1; - else - through=0; - - if(through==0 && (part->flag & PART_DIE_ON_COL || ob->pd->flag & PDEFLE_KILL_PART)){ - pa->dietime = cfra-(1.0f-min_d)*dfra; - VecLerpf(def_loc,def_loc,state->co,min_d); - - VECCOPY(state->co,def_loc); - VecLerpf(state->vel,pa->state.vel,state->vel,min_d); - QuatInterpol(state->rot,pa->state.rot,state->rot,min_d); - VecLerpf(state->ave,pa->state.ave,state->ave,min_d); - - *pa_die=1; + /* particle dies in collision */ + if(through == 0 && (part->flag & PART_DIE_ON_COL || pd->flag & PDEFLE_KILL_PART)) { + pa->alive = PARS_DYING; + pa->dietime = pa->state.time + (cfra - pa->state.time) * dt; + 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); /* particle is dead so we don't need to calculate further */ - deflections=10; + deflections=max_deflections; /* store for reactors */ - copy_particle_key(&cstate,state,0); + copy_particle_key(&reaction_state,state,0); if(part->flag & PART_STICKY){ pa->stick_ob=ob; pa->flag |= PARS_STICKY; } } - else{ - VECCOPY(co1,def_loc); - VECCOPY(co2,state->co); - - if(global==0){ - /* convert particle coordinates to object coordinates */ - Mat4Invert(imat,ob->obmat); - Mat4MulVecfl(imat,co1); - Mat4MulVecfl(imat,co2); - } - - VecLerpf(def_loc,co1,co2,min_d); - - if(radius>0.0f){ - VECSUB(unit_nor,def_loc,ipoint); - } - else{ - /* get deflection point & normal */ - psys_interpolate_face(mvert,mface,0,0,min_w,ipoint,unit_nor,0,0,0,0); - if(global){ - Mat4Mul3Vecfl(ob->obmat,unit_nor); - Mat4MulVecfl(ob->obmat,ipoint); - } - } - - Normalize(unit_nor); - - VECSUB(dvec,co1,co2); - /* scale to remaining length after deflection */ - VecMulf(dvec,1.0f-min_d); - - /* flip normal to face particle */ - if(Inpf(unit_nor,dvec)<0.0f) - VecMulf(unit_nor,-1.0f); - - /* store for easy velocity calculation */ - o_len=VecLength(dvec); - - /* project particle movement to normal & create tangent */ - dotprod=Inpf(dvec,unit_nor); - VECCOPY(def_nor,unit_nor); - VecMulf(def_nor,dotprod); - VECSUB(def_tan,def_nor,dvec); - - damp=ob->pd->pdef_damp+ob->pd->pdef_rdamp*2*(BLI_frand()-0.5f); - - /* create location after deflection */ - VECCOPY(dvec,def_nor); - damp=ob->pd->pdef_damp+ob->pd->pdef_rdamp*2*(BLI_frand()-0.5f); + else { + float nor_vec[3], tan_vec[3], tan_vel[3], vel[3]; + float damp, frict; + float inp, inp_v; + + /* get damping & friction factors */ + damp = pd->pdef_damp + pd->pdef_rdamp * 2 * (BLI_frand() - 0.5f); CLAMP(damp,0.0,1.0); - VecMulf(dvec,1.0f-damp); - if(through) - VecMulf(dvec,-1.0); - - frict=ob->pd->pdef_frict+ob->pd->pdef_rfrict*2.0f*(BLI_frand()-0.5f); + + frict = pd->pdef_frict + pd->pdef_rfrict * 2 * (BLI_frand() - 0.5f); CLAMP(frict,0.0,1.0); - VECADDFAC(dvec,dvec,def_tan,1.0f-frict); - /* store for easy velocity calculation */ - d_len=VecLength(dvec); + /* treat normal & tangent components separately */ + inp = Inpf(col.nor, vec); + inp_v = Inpf(col.nor, col.vel); - /* just to be sure we don't hit the current face again */ - if(through){ - VECADDFAC(ipoint,ipoint,unit_nor,-0.0001f); - VECADDFAC(def_loc,def_loc,unit_nor,-0.0001f); + VECADDFAC(tan_vec, vec, col.nor, -inp); + VECADDFAC(tan_vel, col.vel, col.nor, -inp_v); + if((part->flag & PART_ROT_DYN)==0) + VecLerpf(tan_vec, tan_vec, tan_vel, frict); - if(part->flag & PART_ROT_DYN){ - VECADDFAC(def_tan,def_tan,unit_nor,-0.0001f); - VECADDFAC(def_nor,def_nor,unit_nor,-0.0001f); - } - } - else{ - VECADDFAC(ipoint,ipoint,unit_nor,0.0001f); - VECADDFAC(def_loc,def_loc,unit_nor,0.0001f); + VECCOPY(nor_vec, col.nor); + inp *= 1.0f - damp; - if(part->flag & PART_ROT_DYN){ - VECADDFAC(def_tan,def_tan,unit_nor,0.0001f); - VECADDFAC(def_nor,def_nor,unit_nor,0.0001f); - } + if(through) + inp_v *= damp; + + /* special case for object hitting the particle from behind */ + if(through==0 && ((inp_v>0 && inp>0 && inp_v>inp) || (inp_v<0 && inp<0 && inp_v linear velocity - slightly more physical and looks even nicer than before */ + if(part->flag & PART_ROT_DYN) { + float surface_vel[3], rot_vel[3], friction[3], dave[3], dvel[3]; + + /* apparent velocity along collision surface */ + VECSUB(surface_vel, tan_vec, tan_vel); + + /* direction of rolling friction */ + Crossf(rot_vel, state->ave, col.nor); + /* convert to current dt */ + VecMulf(rot_vel, (timestep*dfra) * (1.0f - col.t)); + VecMulf(rot_vel, pa->size); + + /* apply sliding friction */ + VECSUB(surface_vel, surface_vel, rot_vel); + VECCOPY(friction, surface_vel); + + VecMulf(surface_vel, 1.0 - frict); + VecMulf(friction, frict); + + /* sliding changes angular velocity */ + Crossf(dave, col.nor, friction); + VecMulf(dave, 1.0f/MAX2(pa->size, 0.001)); + + /* we assume rolling friction is around 0.01 of sliding friction */ + VecMulf(rot_vel, 1.0 - frict*0.01); + + /* change in angular velocity has to be added to the linear velocity too */ + Crossf(dvel, dave, col.nor); + VecMulf(dvel, pa->size); + VECADD(rot_vel, rot_vel, dvel); + + VECADD(surface_vel, surface_vel, rot_vel); + VECADD(tan_vec, surface_vel, tan_vel); + + /* 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); } - /* lets get back to global space */ - if(global==0){ - Mat4Mul3Vecfl(ob->obmat,dvec); - Mat4MulVecfl(ob->obmat,ipoint); - Mat4MulVecfl(ob->obmat,def_loc);/* def_loc remains as intersection point for next iteration */ - } + /* combine components together again */ + VECADD(vec, nor_vec, tan_vec); - /* store for reactors */ - VECCOPY(cstate.co,ipoint); - VecLerpf(cstate.vel,pa->state.vel,state->vel,min_d); - QuatInterpol(cstate.rot,pa->state.rot,state->rot,min_d); + /* calculate velocity from collision vector */ + VECCOPY(vel, vec); + VecMulf(vel, 1.0f/MAX2((timestep*dfra) * (1.0f - col.t), 0.00001)); - /* slightly unphysical but looks nice enough */ - if(part->flag & PART_ROT_DYN){ - if(global==0){ - Mat4Mul3Vecfl(ob->obmat,def_nor); - Mat4Mul3Vecfl(ob->obmat,def_tan); - } + /* make sure we don't hit the current face again */ + VECADDFAC(co, co, col.nor, (through ? -0.0001f : 0.0001f)); - Normalize(def_tan); - Normalize(def_nor); - VECCOPY(unit_nor,def_nor); + /* 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); - /* create normal velocity */ - VecMulf(def_nor,Inpf(pa->state.vel,def_nor)); + /* set coordinates for next iteration */ + VECCOPY(col.co1, co); + VECADDFAC(col.co2, co, vec, 1.0f - t); + col.t = dt; - /* create tangential velocity */ - VecMulf(def_tan,Inpf(pa->state.vel,def_tan)); - - /* angular velocity change due to tangential velocity */ - Crossf(dave,unit_nor,def_tan); - VecMulf(dave,1.0f/pa->size); - - /* linear velocity change due to angular velocity */ - VecMulf(unit_nor,pa->size); /* point of impact from particle center */ - Crossf(dvel,pa->state.ave,unit_nor); - - if(through) - VecMulf(def_nor,-1.0); - - VecMulf(def_nor,1.0f-damp); - VECSUB(dvel,dvel,def_nor); - - VecMulf(dvel,1.0f-frict); - VecMulf(dave,1.0f-frict); - } - - if(d_len<0.001 && VecLength(pa->state.vel)<0.001){ + if(VecLength(vec) < 0.001 && VecLength(pa->state.vel) < 0.001) { /* kill speed to stop slipping */ VECCOPY(state->vel,zerovec); - VECCOPY(state->co,def_loc); - if(part->flag & PART_ROT_DYN) + VECCOPY(state->co, co); + if(part->flag & PART_ROT_DYN) { VECCOPY(state->ave,zerovec); - deflections=10; - } - else{ - - /* apply new coordinates */ - VECADD(state->co,def_loc,dvec); - - Normalize(dvec); - - /* we have to use original velocity because otherwise we get slipping */ - /* when forces like gravity balance out damping & friction */ - VecMulf(dvec,VecLength(pa->state.vel)*(d_len/o_len)); - VECCOPY(state->vel,dvec); - - if(part->flag & PART_ROT_DYN){ - VECADD(state->vel,state->vel,dvel); - VecMulf(state->vel,0.5); - VECADD(state->ave,state->ave,dave); - VecMulf(state->ave,0.5); } } + else { + VECCOPY(state->co, col.co2); + VECCOPY(state->vel, vel); + } } deflections++; - cstate.time=cfra-(1.0f-min_d)*dfra; - //particle_react_to_collision(min_ob,pob,psys,pa,p,&cstate); - push_reaction(pob,psys,p,PART_EVENT_COLLIDE,&cstate); + reaction_state.time = cfra - (1.0f - dt) * dfra; + push_reaction(col.ob, psys, p, PART_EVENT_COLLIDE, &reaction_state); } else return; @@ -3482,7 +3402,7 @@ static int add_boid_acc(BoidVecFunc *bvf, float lat_max, float tan_max, float *l } } /* determines the acceleration that the boid tries to acchieve */ -static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, KDTree *tree, float timestep, float cfra, float *acc, int *pa_die) +static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, KDTree *tree, float timestep, float cfra, float *acc) { ParticleData *pars=psys->particles; KDTreeNearest ptn[MAX_BOIDNEIGHBOURS+1]; @@ -3549,7 +3469,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS distance=Normalize(dvec); if(part->flag & PART_DIE_ON_COL && distance < pd->mindist){ - *pa_die=1; + pa->alive = PARS_DYING; pa->dietime=cfra; i=BOID_TOT_RULES; break; @@ -3588,7 +3508,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS distance = Normalize(dvec); if(part->flag & PART_DIE_ON_COL && distance < (epsys->particles+ptn2[p].index)->size){ - *pa_die=1; + pa->alive = PARS_DYING; pa->dietime=cfra; i=BOID_TOT_RULES; break; @@ -3997,7 +3917,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi IpoCurve *icu_esize=find_ipocurve(part->ipo,PART_EMIT_SIZE); Material *ma=give_current_material(ob,part->omat); float timestep; - int p, totpart, pa_die; + int p, totpart; /* current time */ float ctime, ipotime; /* frame & time changes */ @@ -4077,7 +3997,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi psys_init_effectors(ob,part->eff_group,psys); if(psys->effectors.first) - precalc_effectors(ob,psys,psmd); + precalc_effectors(ob,psys,psmd,cfra); if(part->phystype==PART_PHYS_BOIDS){ /* create particle tree for fast inter-particle comparisons */ @@ -4106,15 +4026,13 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi } pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size); - pa_die=0; - birthtime = pa->time + pa->loop * pa->lifetime; + /* allways reset particles to emitter before birth */ if(pa->alive==PARS_UNBORN || pa->alive==PARS_KILLED || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED) || birthtime >= cfra){ - /* allways reset particles to emitter before birth */ reset_particle(pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot); copy_particle_key(key,&pa->state,1); } @@ -4139,32 +4057,31 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi /* particle dies some time between this and last step */ pa_dfra = dietime - psys->cfra; pa_dtime = pa_dfra * timestep; - pa_die = 1; + pa->alive = PARS_DYING; } else if(dietime < cfra){ - /* TODO: figure out if there's something to be done when particle is dead */ + /* nothing to be done when particle is dead */ } copy_particle_key(key,&pa->state,1); - if(dfra>0.0 && pa->alive==PARS_ALIVE){ + 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,pa_dfra,cfra,key,&pa_die); + deflect_particle(ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra,key); /* 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,&pa_die); - if(pa_die==0) + 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; } @@ -4172,7 +4089,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi push_reaction(ob,psys,p,PART_EVENT_NEAR,key); - if(pa_die){ + if(pa->alive == PARS_DYING){ push_reaction(ob,psys,p,PART_EVENT_DEATH,key); if(part->flag & PART_LOOP && part->type!=PART_HAIR){ @@ -4194,6 +4111,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi } } } + /* apply outstates to particles */ for(p=0, pa=psys->particles, key=outstate; pstate,key,1); @@ -4273,7 +4191,7 @@ static void hair_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSyst psys_init_effectors(ob,part->eff_group,psys); if(psys->effectors.first) - precalc_effectors(ob,psys,psmd); + precalc_effectors(ob,psys,psmd,cfra); if(psys_in_edit_mode(psys)) PE_recalc_world_cos(ob, psys); @@ -4301,7 +4219,7 @@ static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSy //if(part->flag & (PART_BAKED_GUIDES+PART_BAKED_DEATHS)){ psys_init_effectors(ob,part->eff_group,psys); if(psys->effectors.first) - precalc_effectors(ob,psys,psmd); + precalc_effectors(ob,psys,psmd,cfra); //} disp= (float)get_current_display_percentage(psys)/50.0f-1.0f; diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index c60535cade2..76af9a763ee 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -301,7 +301,7 @@ int normal_projection_project_vertex(char options, const float *vert, const floa hit_tmp.index = -1; - BLI_bvhtree_ray_cast(tree, co, no, &hit_tmp, callback, userdata); + BLI_bvhtree_ray_cast(tree, co, no, 0.0f, &hit_tmp, callback, userdata); if(hit_tmp.index != -1) { diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index 6d9a17efebf..e3591a84e98 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -54,6 +54,7 @@ typedef struct BVHTreeRay { float origin[3]; /* ray origin */ float direction[3]; /* ray direction */ + float radius; /* radius around ray */ } BVHTreeRay; typedef struct BVHTreeRayHit @@ -90,7 +91,7 @@ float BLI_bvhtree_getepsilon(BVHTree *tree); /* find nearest node to the given coordinates (if nearest is given it will only search nodes where square distance is smaller than nearest->dist) */ int BLI_bvhtree_find_nearest(BVHTree *tree, const float *co, BVHTreeNearest *nearest, BVHTree_NearestPointCallback callback, void *userdata); -int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata); +int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata); #endif // BLI_KDOPBVH_H diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 9f82a816147..30472beb3e6 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -1414,14 +1414,14 @@ static float ray_nearest_hit(BVHRayCastData *data, BVHNode *node) if(data->ray_dot_axis[i] == 0.0f) { //axis aligned ray - if(data->ray.origin[i] < bv[0] - || data->ray.origin[i] > bv[1]) + if(data->ray.origin[i] < bv[0] - data->ray.radius + || data->ray.origin[i] > bv[1] + data->ray.radius) return FLT_MAX; } else { - float ll = (bv[0] - data->ray.origin[i]) / data->ray_dot_axis[i]; - float lu = (bv[1] - data->ray.origin[i]) / data->ray_dot_axis[i]; + float ll = (bv[0] - data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; + float lu = (bv[1] + data->ray.radius - data->ray.origin[i]) / data->ray_dot_axis[i]; if(data->ray_dot_axis[i] > 0.0f) { @@ -1480,7 +1480,7 @@ static void dfs_raycast(BVHRayCastData *data, BVHNode *node) } } -int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) +int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, float radius, BVHTreeRayHit *hit, BVHTree_RayCastCallback callback, void *userdata) { int i; BVHRayCastData data; @@ -1493,6 +1493,7 @@ int BLI_bvhtree_ray_cast(BVHTree *tree, const float *co, const float *dir, BVHTr VECCOPY(data.ray.origin, co); VECCOPY(data.ray.direction, dir); + data.ray.radius = radius; Normalize(data.ray.direction); diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 363f0075e23..8618bee3638 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -416,6 +416,7 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in #define PARS_DEAD 1 #define PARS_UNBORN 2 #define PARS_ALIVE 3 +#define PARS_DYING 4 /* psys->vg */ #define PSYS_TOT_VG 12 From fa825e70e3d5f05a1a803d2be563c3b919adf4ed Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 13 Sep 2008 19:19:51 +0000 Subject: [PATCH 051/125] Game engine: added Rasterizer.get/setMaterialMode to set texface, multitexture or glsl materials. This does not affect existing scenes, only newly created ones. --- .../BlenderRoutines/BL_KetsjiEmbedStart.cpp | 12 +-- .../GamePlayer/ghost/GPG_Application.cpp | 21 +++-- source/gameengine/Ketsji/KX_PythonInit.cpp | 77 ++++++++++++++++--- source/gameengine/PyDoc/Rasterizer.py | 19 +++++ 4 files changed, 102 insertions(+), 27 deletions(-) diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 1f66335c749..fa771cb3ce8 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -138,10 +138,12 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, bool usemat = false, useglslmat = false; if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) - usemat = (SYS_GetCommandLineInt(syshandle, "blender_material", 0) != 0); + usemat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0); if(GPU_extensions_minimum_support()) - useglslmat = (SYS_GetCommandLineInt(syshandle, "blender_glsl_material", 0) != 0); + useglslmat = (SYS_GetCommandLineInt(syshandle, "blender_glsl_material", 1) != 0); + else if(G.fileflags & G_FILE_GAME_MAT_GLSL) + usemat = false; // create the canvas, rasterizer and rendertools RAS_ICanvas* canvas = new KX_BlenderCanvas(area); @@ -299,10 +301,10 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, sceneconverter->addInitFromFrame=false; if (always_use_expand_framing) sceneconverter->SetAlwaysUseExpandFraming(true); - - if(usemat) + + if(usemat && (G.fileflags & G_FILE_GAME_MAT)) sceneconverter->SetMaterials(true); - if(useglslmat) + if(useglslmat && (G.fileflags & G_FILE_GAME_MAT_GLSL)) sceneconverter->SetGLSLMaterials(true); KX_Scene* startscene = new KX_Scene(keyboarddevice, diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 0287178004d..580c80ee0a5 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -524,17 +524,14 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", G.fileflags & G_FILE_DISPLAY_LISTS) != 0); - if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) { - int gameflag =(G.fileflags & G_FILE_GAME_MAT); - m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", gameflag) != 0); - } + if(GLEW_ARB_multitexture && GLEW_VERSION_1_1) + m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0); - if(GPU_extensions_minimum_support()) { - int gameflag = (G.fileflags & G_FILE_GAME_MAT_GLSL); + if(GPU_extensions_minimum_support()) + m_blenderglslmat = (SYS_GetCommandLineInt(syshandle, "blender_glsl_material", 1) != 0); + else if(G.fileflags & G_FILE_GAME_MAT_GLSL) + m_blendermat = false; - m_blenderglslmat = (SYS_GetCommandLineInt(syshandle, "blender_glsl_material", gameflag) != 0); - } - // create the canvas, rasterizer and rendertools m_canvas = new GPG_Canvas(window); if (!m_canvas) @@ -657,12 +654,12 @@ bool GPG_Application::startEngine(void) { STR_String startscenename = m_startSceneName.Ptr(); m_ketsjiengine->SetSceneConverter(m_sceneconverter); - + // if (always_use_expand_framing) // sceneconverter->SetAlwaysUseExpandFraming(true); - if(m_blendermat) + if(m_blendermat && (G.fileflags & G_FILE_GAME_MAT)) m_sceneconverter->SetMaterials(true); - if(m_blenderglslmat) + if(m_blenderglslmat && (G.fileflags & G_FILE_GAME_MAT_GLSL)) m_sceneconverter->SetGLSLMaterials(true); KX_Scene* startscene = new KX_Scene(m_keyboard, diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 5742c530f6d..5308a0b9536 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -303,7 +303,7 @@ static PyObject* gPyGetBlendFileList(PyObject*, PyObject* args) if((dp = opendir(cpath)) == NULL) { /* todo, show the errno, this shouldnt happen anyway if the blendfile is readable */ - fprintf(stderr, "Could not read directoty () failed, code %d (%s)\n", cpath, errno, strerror(errno)); + fprintf(stderr, "Could not read directoty (%s) failed, code %d (%s)\n", cpath, errno, strerror(errno)); return list; } @@ -696,7 +696,7 @@ static PyObject* gPySetGLSLMaterialSetting(PyObject*, PyObject*) { char *setting; - int enable, flag; + int enable, flag, fileflags; if (!PyArg_ParseTuple(args,"si",&setting,&enable)) return NULL; @@ -707,6 +707,8 @@ static PyObject* gPySetGLSLMaterialSetting(PyObject*, PyErr_SetString(PyExc_ValueError, "glsl setting is not known"); return NULL; } + + fileflags = G.fileflags; if (enable) G.fileflags &= ~flag; @@ -714,17 +716,19 @@ static PyObject* gPySetGLSLMaterialSetting(PyObject*, G.fileflags |= flag; /* display lists and GLSL materials need to be remade */ - if(gp_KetsjiEngine) { - KX_SceneList *scenes = gp_KetsjiEngine->CurrentScenes(); - KX_SceneList::iterator it; + if(G.fileflags != fileflags) { + if(gp_KetsjiEngine) { + KX_SceneList *scenes = gp_KetsjiEngine->CurrentScenes(); + KX_SceneList::iterator it; - for(it=scenes->begin(); it!=scenes->end(); it++) - if((*it)->GetBucketManager()) - (*it)->GetBucketManager()->ReleaseDisplayLists(); + for(it=scenes->begin(); it!=scenes->end(); it++) + if((*it)->GetBucketManager()) + (*it)->GetBucketManager()->ReleaseDisplayLists(); + } + + GPU_materials_free(); } - GPU_materials_free(); - Py_RETURN_NONE; } @@ -749,6 +753,50 @@ static PyObject* gPyGetGLSLMaterialSetting(PyObject*, return PyInt_FromLong(enabled); } +#define KX_TEXFACE_MATERIAL 0 +#define KX_BLENDER_MULTITEX_MATERIAL 1 +#define KX_BLENDER_GLSL_MATERIAL 2 + +static PyObject* gPySetMaterialType(PyObject*, + PyObject* args, + PyObject*) +{ + int flag, type; + + if (!PyArg_ParseTuple(args,"i",&type)) + return NULL; + + if(type == KX_BLENDER_GLSL_MATERIAL) + flag = G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL; + else if(type == KX_BLENDER_MULTITEX_MATERIAL) + flag = G_FILE_GAME_MAT; + else if(type == KX_TEXFACE_MATERIAL) + flag = 0; + else { + PyErr_SetString(PyExc_ValueError, "material type is not known"); + return NULL; + } + + G.fileflags &= ~(G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL); + G.fileflags |= flag; + + Py_RETURN_NONE; +} + +static PyObject* gPyGetMaterialType(PyObject*) +{ + int flag; + + if(G.fileflags & (G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL)) + flag = KX_BLENDER_GLSL_MATERIAL; + else if(G.fileflags & G_FILE_GAME_MAT) + flag = KX_BLENDER_MULTITEX_MATERIAL; + else + flag = KX_TEXFACE_MATERIAL; + + return PyInt_FromLong(flag); +} + STR_String gPyGetWindowHeight__doc__="getWindowHeight doc"; STR_String gPyGetWindowWidth__doc__="getWindowWidth doc"; STR_String gPyEnableVisibility__doc__="enableVisibility doc"; @@ -782,6 +830,10 @@ static struct PyMethodDef rasterizer_methods[] = { {"getEyeSeparation", (PyCFunction) gPyGetEyeSeparation, METH_VARARGS, "get the eye separation for stereo mode"}, {"setFocalLength", (PyCFunction) gPySetFocalLength, METH_VARARGS, "set the focal length for stereo mode"}, {"getFocalLength", (PyCFunction) gPyGetFocalLength, METH_VARARGS, "get the focal length for stereo mode"}, + {"setMaterialMode",(PyCFunction) gPySetMaterialType, + METH_VARARGS, "set the material mode to use for OpenGL rendering"}, + {"getMaterialMode",(PyCFunction) gPyGetMaterialType, + METH_NOARGS, "get the material mode being used for OpenGL rendering"}, {"setGLSLMaterialSetting",(PyCFunction) gPySetGLSLMaterialSetting, METH_VARARGS, "set the state of a GLSL material setting"}, {"getGLSLMaterialSetting",(PyCFunction) gPyGetGLSLMaterialSetting, @@ -1111,6 +1163,11 @@ PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) ErrorObject = PyString_FromString("Rasterizer.error"); PyDict_SetItemString(d, "error", ErrorObject); + /* needed for get/setMaterialType */ + KX_MACRO_addTypesToDict(d, KX_TEXFACE_MATERIAL, KX_TEXFACE_MATERIAL); + KX_MACRO_addTypesToDict(d, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL); + KX_MACRO_addTypesToDict(d, KX_BLENDER_GLSL_MATERIAL, KX_BLENDER_GLSL_MATERIAL); + // XXXX Add constants here // Check for errors diff --git a/source/gameengine/PyDoc/Rasterizer.py b/source/gameengine/PyDoc/Rasterizer.py index 7afdcf07f2e..ebb5332d98d 100644 --- a/source/gameengine/PyDoc/Rasterizer.py +++ b/source/gameengine/PyDoc/Rasterizer.py @@ -37,6 +37,10 @@ Example Uses an L{SCA_MouseSensor}, and two L{KX_ObjectActuator}s to implement M # Centre the mouse Rasterizer.setMousePosition(Rasterizer.getWindowWidth()/2, Rasterizer.getWindowHeight()/2) +@group Material Types: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL +@var KX_TEXFACE_MATERIAL: Materials as defined by the texture face settings. +@var KX_BLENDER_MULTITEX_MATERIAL: Materials approximating blender materials with multitexturing. +@var KX_BLENDER_BLENDER_MATERIAL: Materials approximating blender materials with GLSL. """ @@ -147,6 +151,21 @@ def getFocalLength(): @rtype: float """ +def setMaterialMode(mode): + """ + Set the material mode to use for OpenGL rendering. + + @type mode: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL + @note: Changes will only affect newly created scenes. + """ + +def getMaterialMode(mode): + """ + Get the material mode to use for OpenGL rendering. + + @rtype: KX_TEXFACE_MATERIAL, KX_BLENDER_MULTITEX_MATERIAL, KX_BLENDER_GLSL_MATERIAL + """ + def setGLSLMaterialSetting(setting, enable): """ Enables or disables a GLSL material setting. From 06be41648ffe7be565fe5a1e117e3611384c667f Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Sat, 13 Sep 2008 21:06:22 +0000 Subject: [PATCH 052/125] Fix for #11740 - Reactor particles do not render in animation. - Particle data was deleted when the current frame was outside the baked range. Reactor particles need this data to store birth and death times. --- source/blender/blenkernel/BKE_particle.h | 1 + source/blender/blenkernel/intern/particle_system.c | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 944a9081679..ea1dc7407db 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -302,6 +302,7 @@ int psys_particle_dm_face_lookup(struct Object *ob, struct DerivedMesh *dm, int #define PSYS_RESET_ALL 1 #define PSYS_RESET_DEPSGRAPH 2 #define PSYS_RESET_CHILDREN 3 +#define PSYS_RESET_CACHE_MISS 4 /* ParticleEffectorCache->type */ #define PSYS_EC_EFFECTOR 1 diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index bac92af5bee..df193bc3802 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -150,6 +150,14 @@ void psys_reset(ParticleSystem *psys, int mode) BLI_freelistN(&psys->reactevents); } } + else if(mode == PSYS_RESET_CACHE_MISS) { + /* set all particles to be skipped */ + ParticleData *pa = psys->particles; + int p=0; + + for(; ptotpart; p++, pa++) + pa->flag = PARS_NO_DISP; + } /* reset children */ if(psys->child) { @@ -4473,7 +4481,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier if(usecache) { /* frame clamping */ if(framenr < startframe) { - psys_reset(psys, PSYS_RESET_DEPSGRAPH); + psys_reset(psys, PSYS_RESET_CACHE_MISS); psys->cfra = cfra; psys->recalc = 0; return; @@ -4553,14 +4561,14 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier return; } else if(ob->id.lib || (cache->flag & PTCACHE_BAKED)) { - psys_reset(psys, PSYS_RESET_DEPSGRAPH); + psys_reset(psys, PSYS_RESET_CACHE_MISS); psys->cfra=cfra; psys->recalc = 0; return; } if(framenr != startframe && framedelta != 1) { - psys_reset(psys, PSYS_RESET_DEPSGRAPH); + psys_reset(psys, PSYS_RESET_CACHE_MISS); psys->cfra = cfra; psys->recalc = 0; return; From 704fef314a6a4ed17ad93cb32f1821c337ddb7d5 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 14 Sep 2008 00:32:18 +0000 Subject: [PATCH 053/125] Various game engine fixes: * Fix issue with add transparency mode with blender materials. * Possible fix at frontface flip in the game engine. * Fix color buffering clearing for multiple viewports, it used to clear as if there was one. * Fix for zoom level in user defined viewports, it was based on the full window before, now it is based on the viewport itself. * For user defined viewports, always use Expose instead of Letterbox with bars, the latter doesn't make sense then. --- source/blender/blenloader/intern/readfile.c | 2 +- .../Converter/BL_BlenderDataConversion.cpp | 2 +- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 3 +- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 148 ++++++++++++------ source/gameengine/Ketsji/KX_KetsjiEngine.h | 3 +- .../Rasterizer/RAS_BucketManager.cpp | 21 +-- .../Rasterizer/RAS_FramingManager.h | 15 +- .../gameengine/Rasterizer/RAS_IRasterizer.h | 8 +- .../RAS_OpenGLRasterizer.cpp | 37 +++-- .../RAS_OpenGLRasterizer.h | 3 +- 10 files changed, 146 insertions(+), 96 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 6b720851b0d..da85a264a0c 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7762,7 +7762,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - if(main->versionfile <= 246 && main->subversionfile < 1){ + if(main->versionfile < 246 || (main->versionfile == 246 && main->subversionfile < 1)) { Mesh *me; for(me=main->mesh.first; me; me= me->id.next) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 05d4f45b634..7a04a42e90d 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -627,7 +627,7 @@ BL_Material* ConvertMaterial( material->transp = TF_ALPHA; // always zsort alpha + add - if((material->transp == TF_ALPHA || texalpha) && (material->transp != TF_CLIP)) { + if((material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha) && (material->transp != TF_CLIP)) { material->ras_mode |= ALPHA; material->ras_mode |= (material->mode & TF_ALPHASORT)? ZSORT: 0; } diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 0b4fde61e1c..4d24ba195cc 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -629,7 +629,8 @@ int main(int argc, char** argv) char pathname[160]; get_filename(argc, argv, filename); - make_absolute_filename(filename); + if(filename[0]) + make_absolute_filename(filename); do { diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index cf98bb72601..4d83853537e 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -276,30 +276,73 @@ void KX_KetsjiEngine::StartEngine(bool clearIpo) } +void KX_KetsjiEngine::ClearFrame() +{ + // clear unless we're drawing overlapping stereo + if(m_rasterizer->InterlacedStereo() && + m_rasterizer->GetEye() == RAS_IRasterizer::RAS_STEREO_RIGHTEYE) + return; + + // clear the viewports with the background color of the first scene + bool doclear = false; + KX_SceneList::iterator sceneit; + RAS_Rect clearvp, area, viewport; + + for (sceneit = m_scenes.begin(); sceneit != m_scenes.end(); sceneit++) + { + KX_Scene* scene = *sceneit; + //const RAS_FrameSettings &framesettings = scene->GetFramingType(); + list* cameras = scene->GetCameras(); + + list::iterator it; + for(it = cameras->begin(); it != cameras->end(); it++) + { + SetupViewport(scene, (*it), area, viewport); + + if(!doclear) { + clearvp = viewport; + doclear = true; + } + else { + if(viewport.GetLeft() < clearvp.GetLeft()) + clearvp.SetLeft(viewport.GetLeft()); + if(viewport.GetBottom() < clearvp.GetBottom()) + clearvp.SetBottom(viewport.GetBottom()); + if(viewport.GetRight() > clearvp.GetRight()) + clearvp.SetRight(viewport.GetRight()); + if(viewport.GetTop() > clearvp.GetTop()) + clearvp.SetTop(viewport.GetTop()); + + } + } + } + + if(doclear) { + KX_Scene* firstscene = *m_scenes.begin(); + SetBackGround(firstscene->GetWorldInfo()); + + m_canvas->SetViewPort(clearvp.GetLeft(), clearvp.GetBottom(), + clearvp.GetRight(), clearvp.GetTop()); + m_rasterizer->ClearColorBuffer(); + } +} + bool KX_KetsjiEngine::BeginFrame() { - bool result = false; - - RAS_Rect vp; - KX_Scene* firstscene = *m_scenes.begin(); - const RAS_FrameSettings &framesettings = firstscene->GetFramingType(); - - // set the area used for rendering + // set the area used for rendering (stereo can assign only a subset) m_rasterizer->SetRenderArea(); - RAS_FramingManager::ComputeViewport(framesettings, m_canvas->GetDisplayArea(), vp); - if (m_canvas->BeginDraw()) { - result = true; + ClearFrame(); - m_canvas->SetViewPort(vp.GetLeft(), vp.GetBottom(), vp.GetRight(), vp.GetTop()); - SetBackGround( firstscene->GetWorldInfo() ); - m_rasterizer->BeginFrame( m_drawingmode , m_kxsystem->GetTimeInSeconds()); - m_rendertools->BeginFrame( m_rasterizer); + m_rasterizer->BeginFrame(m_drawingmode , m_kxsystem->GetTimeInSeconds()); + m_rendertools->BeginFrame(m_rasterizer); + + return true; } - return result; + return false; } @@ -606,7 +649,7 @@ void KX_KetsjiEngine::Render() ); } // clear the -whole- viewport - m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER); + m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER); } m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_LEFTEYE); @@ -635,9 +678,6 @@ void KX_KetsjiEngine::Render() m_rendertools->SetAuxilaryClientInfo(scene); - //Initialize scene viewport. - SetupRenderFrame(scene, cam); - // do the rendering RenderFrame(scene, cam); } @@ -655,9 +695,6 @@ void KX_KetsjiEngine::Render() m_rendertools->SetAuxilaryClientInfo(scene); - //Initialize scene viewport. - SetupRenderFrame(scene, (*it)); - // do the rendering RenderFrame(scene, (*it)); } @@ -690,10 +727,6 @@ void KX_KetsjiEngine::Render() //pass the scene, for picking and raycasting (shadows) m_rendertools->SetAuxilaryClientInfo(scene); - //Initialize scene viewport. - //SetupRenderFrame(scene); - SetupRenderFrame(scene, cam); - // do the rendering //RenderFrame(scene); RenderFrame(scene, cam); @@ -854,7 +887,7 @@ void KX_KetsjiEngine::SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat) } -void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam) +void KX_KetsjiEngine::SetupViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport) { // In this function we make sure the rasterizer settings are upto // date. We compute the viewport so that logic @@ -862,17 +895,26 @@ void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam) // Note we postpone computation of the projection matrix // so that we are using the latest camera position. - - RAS_Rect viewport; - - if (!cam) - return; - if (cam->GetViewport()) { - viewport.SetLeft(cam->GetViewportLeft()); - viewport.SetBottom(cam->GetViewportBottom()); - viewport.SetRight(cam->GetViewportRight()); - viewport.SetTop(cam->GetViewportTop()); + RAS_Rect userviewport; + + userviewport.SetLeft(cam->GetViewportLeft()); + userviewport.SetBottom(cam->GetViewportBottom()); + userviewport.SetRight(cam->GetViewportRight()); + userviewport.SetTop(cam->GetViewportTop()); + + // Don't do bars on user specified viewport + RAS_FrameSettings settings = scene->GetFramingType(); + if(settings.FrameType() == RAS_FrameSettings::e_frame_bars) + settings.SetFrameType(RAS_FrameSettings::e_frame_extend); + + RAS_FramingManager::ComputeViewport( + scene->GetFramingType(), + userviewport, + viewport + ); + + area = userviewport; } else if ( m_overrideCam || (scene->GetName() != m_overrideSceneName) || m_overrideCamUseOrtho ) { RAS_FramingManager::ComputeViewport( @@ -880,24 +922,16 @@ void KX_KetsjiEngine::SetupRenderFrame(KX_Scene *scene, KX_Camera* cam) m_canvas->GetDisplayArea(), viewport ); + + area = m_canvas->GetDisplayArea(); } else { viewport.SetLeft(0); viewport.SetBottom(0); viewport.SetRight(int(m_canvas->GetWidth())); viewport.SetTop(int(m_canvas->GetHeight())); + + area = m_canvas->GetDisplayArea(); } - // store the computed viewport in the scene - - scene->SetSceneViewport(viewport); - - // set the viewport for this frame and scene - m_canvas->SetViewPort( - viewport.GetLeft(), - viewport.GetBottom(), - viewport.GetRight(), - viewport.GetTop() - ); - } void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) @@ -951,12 +985,22 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) // update graphics void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) { + RAS_Rect viewport, area; float left, right, bottom, top, nearfrust, farfrust, focallength; const float ortho = 100.0; // KX_Camera* cam = scene->GetActiveCamera(); if (!cam) return; + + SetupViewport(scene, cam, area, viewport); + + // store the computed viewport in the scene + scene->SetSceneViewport(viewport); + + // set the viewport for this frame and scene + m_canvas->SetViewPort(viewport.GetLeft(), viewport.GetBottom(), + viewport.GetRight(), viewport.GetTop()); // see KX_BlenderMaterial::Activate //m_rasterizer->SetAmbient(); @@ -985,8 +1029,8 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) RAS_FramingManager::ComputeFrustum( scene->GetFramingType(), - m_canvas->GetDisplayArea(), - scene->GetSceneViewport(), + area, + viewport, lens, nearfrust, farfrust, @@ -1002,7 +1046,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix( left, right, bottom, top, nearfrust, farfrust, focallength); - + cam->SetProjectionMatrix(projmat); // Otherwise the projection matrix for each eye will be the same... diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 97458362f0f..89f6fe55045 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -177,7 +177,7 @@ private: /** Blue component of framing bar color. */ float m_overrideFrameColorB; - void SetupRenderFrame(KX_Scene *scene, KX_Camera* cam); + void SetupViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport); void RenderFrame(KX_Scene* scene, KX_Camera* cam); void PostRenderFrame(); void RenderDebugProperties(); @@ -355,6 +355,7 @@ protected: KX_Scene* CreateScene(const STR_String& scenename); bool BeginFrame(); + void ClearFrame(); void EndFrame(); }; diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp index 9fb21a3c17b..f7938bb62e6 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp +++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp @@ -130,9 +130,6 @@ void RAS_BucketManager::OrderBuckets(const MT_Transform& cameratrans, BucketList sort(slots.begin(), slots.end(), fronttoback()); } -//static int TOTASLOT = 0; -//static int TOTSLOT = 0; - void RAS_BucketManager::RenderAlphaBuckets( const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) { @@ -149,10 +146,8 @@ void RAS_BucketManager::RenderAlphaBuckets( for(sit=slots.begin(); sit!=slots.end(); ++sit) { rendertools->SetClientObject(rasty, sit->m_ms->m_clientObj); - while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools)) { + while(sit->m_bucket->ActivateMaterial(cameratrans, rasty, rendertools)) sit->m_bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *(sit->m_ms)); - //TOTASLOT++; - } } rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); @@ -173,13 +168,14 @@ void RAS_BucketManager::RenderSolidBuckets( rendertools->SetClientObject(rasty, mit->m_clientObj); - while ((*bit)->ActivateMaterial(cameratrans, rasty, rendertools)) { + while ((*bit)->ActivateMaterial(cameratrans, rasty, rendertools)) (*bit)->RenderMeshSlot(cameratrans, rasty, rendertools, *mit); - //TOTSLOT++; - } } } + /* this code draws meshes order front-to-back instead to reduce overdraw. + * it turned out slower due to much material state switching, a more clever + * algorithm might do better. */ #if 0 vector slots; vector::iterator sit; @@ -198,17 +194,12 @@ void RAS_BucketManager::RenderSolidBuckets( void RAS_BucketManager::Renderbuckets( const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) { - // beginning each frame, clear (texture/material) caching information + /* beginning each frame, clear (texture/material) caching information */ rasty->ClearCachingInfo(); - //TOTASLOT = 0; - //TOTSLOT = 0; - RenderSolidBuckets(cameratrans, rasty, rendertools); RenderAlphaBuckets(cameratrans, rasty, rendertools); - //printf("total slots = %d = %d + %d\n", TOTSLOT + TOTASLOT, TOTSLOT, TOTASLOT); - rendertools->SetClientObject(rasty, NULL); } diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.h b/source/gameengine/Rasterizer/RAS_FramingManager.h index dcb48c1c2a0..9cb59f300f7 100644 --- a/source/gameengine/Rasterizer/RAS_FramingManager.h +++ b/source/gameengine/Rasterizer/RAS_FramingManager.h @@ -108,6 +108,13 @@ public : ) const { return m_frame_type; }; + + void + SetFrameType( + RAS_FrameType type + ) { + m_frame_type = type; + }; float BarRed( @@ -140,14 +147,6 @@ public : }; private : - - /** - * private to force use of public constructor - */ - - RAS_FrameSettings( - const RAS_FrameSettings & - ); RAS_FrameType m_frame_type; float m_bar_r; diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index 1d18d02a583..411b28fa3b7 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -168,6 +168,10 @@ public: * BeginFrame is called at the start of each frame. */ virtual bool BeginFrame(int drawingmode, double time)=0; + /** + * ClearColorBuffer clears the color buffer. + */ + virtual void ClearColorBuffer()=0; /** * ClearDepthBuffer clears the depth buffer. */ @@ -181,7 +185,8 @@ public: */ virtual void EndFrame()=0; /** - * SetRenderArea sets the render area from the 2d canvas + * SetRenderArea sets the render area from the 2d canvas. + * Returns true if only of subset of the canvas is used. */ virtual void SetRenderArea()=0; @@ -195,6 +200,7 @@ public: * @return true if stereo mode is enabled. */ virtual bool Stereo()=0; + virtual bool InterlacedStereo()=0; /** * Sets which eye buffer subsequent primitives will be rendered to. */ diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 62ee2edb731..4f31ae7fcbc 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -105,8 +105,12 @@ bool RAS_OpenGLRasterizer::Init() m_ambg = 0.0f; m_ambb = 0.0f; - SetBlendingMode(GPU_BLEND_SOLID); - SetFrontFace(true); + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + m_last_blendmode = GPU_BLEND_SOLID; + + glFrontFace(GL_CCW); + m_last_frontface = true; glClearColor(m_redback,m_greenback,m_blueback,m_alphaback); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); @@ -250,21 +254,10 @@ void RAS_OpenGLRasterizer::Exit() EndFrame(); } -bool RAS_OpenGLRasterizer::InterlacedStereo() const -{ - return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED; -} - bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) { m_time = time; m_drawingmode = drawingmode; - - if (!InterlacedStereo() || m_curreye == RAS_STEREO_LEFTEYE) - { - m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback); - m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER); - } // Blender camera routine destroys the settings if (m_drawingmode < KX_SOLID) @@ -278,8 +271,12 @@ bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) glEnable (GL_CULL_FACE); } - SetBlendingMode(GPU_BLEND_SOLID); - SetFrontFace(true); + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + m_last_blendmode = GPU_BLEND_SOLID; + + glFrontFace(GL_CCW); + m_last_frontface = true; glShadeModel(GL_SMOOTH); @@ -310,6 +307,12 @@ void RAS_OpenGLRasterizer::SetDepthMask(DepthMask depthmask) } +void RAS_OpenGLRasterizer::ClearColorBuffer() +{ + m_2DCanvas->ClearColor(m_redback,m_greenback,m_blueback,m_alphaback); + m_2DCanvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER); +} + void RAS_OpenGLRasterizer::ClearDepthBuffer() { @@ -420,6 +423,10 @@ bool RAS_OpenGLRasterizer::Stereo() return true; } +bool RAS_OpenGLRasterizer::InterlacedStereo() +{ + return m_stereomode == RAS_STEREO_VINTERLACE || m_stereomode == RAS_STEREO_INTERLACED; +} void RAS_OpenGLRasterizer::SetEye(const StereoEye eye) { diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 368bd4312ac..0717cce0ce8 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -88,7 +88,6 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer float m_focallength; bool m_setfocallength; int m_noOfScanlines; - bool InterlacedStereo() const; //motion blur int m_motionblur; @@ -131,6 +130,7 @@ public: virtual bool Init(); virtual void Exit(); virtual bool BeginFrame(int drawingmode, double time); + virtual void ClearColorBuffer(); virtual void ClearDepthBuffer(); virtual void ClearCachingInfo(void); virtual void EndFrame(); @@ -138,6 +138,7 @@ public: virtual void SetStereoMode(const StereoMode stereomode); virtual bool Stereo(); + virtual bool InterlacedStereo(); virtual void SetEye(const StereoEye eye); virtual StereoEye GetEye(); virtual void SetEyeSeparation(const float eyeseparation); From c4cde9a02724abdf1488634fc39d2d822907278e Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 14 Sep 2008 01:10:45 +0000 Subject: [PATCH 054/125] Fix for bug #7097: blender multitexture materials in the game engine player did not enable mipmapping when falling back to texfaces. Also commented out code that disabled mipmapping in the player on Mac OS X. If that is a workaround for a bug it is a really poor one, and hopefully fixed now since this code is from 2002 or earlier. --- source/gameengine/Converter/BL_BlenderDataConversion.cpp | 1 + source/gameengine/GamePlayer/ghost/GPG_ghost.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 7a04a42e90d..4851b7f9b08 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -377,6 +377,7 @@ BL_Material* ConvertMaterial( material->texname[i] = material->img[i]->id.name; material->flag[i] |= ( tface->transp &TF_ALPHA )?USEALPHA:0; material->flag[i] |= ( tface->transp &TF_ADD )?CALCALPHA:0; + material->flag[i] |= MIPMAP; if(material->img[i]->flag & IMA_REFLECT) material->mapping[i].mapping |= USEREFL; diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 4d24ba195cc..b0950fece5f 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -594,7 +594,7 @@ int main(int argc, char** argv) { #ifdef __APPLE__ //SYS_WriteCommandLineInt(syshandle, "show_framerate", 1); - SYS_WriteCommandLineInt(syshandle, "nomipmap", 1); + //SYS_WriteCommandLineInt(syshandle, "nomipmap", 1); //fullScreen = false; // Can't use full screen #endif From d111983064296dc9dd2c1b3f1735efd38f95c9d1 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 14 Sep 2008 03:51:51 +0000 Subject: [PATCH 055/125] Fix for bug #5758 and #17585: armatures with IK constraint did not work in the game player, now the IK lib is linked into the player. Makefiles/Scons/CMake buildsystems have been updated. Fix materials nodes to work in the game player. --- blenderplayer/CMakeLists.txt | 1 + intern/iksolver/CMakeLists.txt | 2 +- intern/iksolver/SConscript | 3 ++- source/Makefile | 4 ++-- .../blenkernel/bad_level_call_stubs/stubs.c | 24 ------------------- source/creator/CMakeLists.txt | 4 ++-- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 5 ++++ 7 files changed, 13 insertions(+), 30 deletions(-) diff --git a/blenderplayer/CMakeLists.txt b/blenderplayer/CMakeLists.txt index e32390466c7..9786b7e61b2 100644 --- a/blenderplayer/CMakeLists.txt +++ b/blenderplayer/CMakeLists.txt @@ -86,6 +86,7 @@ IF(UNIX) bf_oglrasterizer bf_expressions bf_scenegraph + bf_IK bf_moto bf_soundsystem bf_kernel diff --git a/intern/iksolver/CMakeLists.txt b/intern/iksolver/CMakeLists.txt index da69f2a3332..736a2a78bb2 100644 --- a/intern/iksolver/CMakeLists.txt +++ b/intern/iksolver/CMakeLists.txt @@ -28,5 +28,5 @@ SET(INC intern ../moto/include ../memutil) FILE(GLOB SRC intern/*.cpp) -BLENDERLIB_NOLIST(blender_IK "${SRC}" "${INC}") +BLENDERLIB(bf_IK "${SRC}" "${INC}") #, libtype=['blender'], priority = [10] ) diff --git a/intern/iksolver/SConscript b/intern/iksolver/SConscript index 81bf61dfcd8..543ee46487c 100644 --- a/intern/iksolver/SConscript +++ b/intern/iksolver/SConscript @@ -5,4 +5,5 @@ sources = env.Glob('intern/*.cpp') incs = 'intern ../moto/include ../memutil' -env.BlenderLib ('blender_IK', sources, Split(incs), [], libtype='blender', priority=10 ) +env.BlenderLib ('bf_IK', sources, Split(incs), [], libtype=['intern','player'], priority=[20,100] ) + diff --git a/source/Makefile b/source/Makefile index 37833a5829c..99155206987 100644 --- a/source/Makefile +++ b/source/Makefile @@ -100,6 +100,7 @@ COMLIB += $(OCGDIR)/blender/nodes_cmp/$(DEBUG_DIR)libnodes_cmp.a COMLIB += $(OCGDIR)/blender/nodes/$(DEBUG_DIR)libnodes.a COMLIB += $(OCGDIR)/blender/imbuf/$(DEBUG_DIR)libimbuf.a COMLIB += $(OCGDIR)/blender/blenlib/$(DEBUG_DIR)libblenlib.a +COMLIB += $(NAN_IKSOLVER)/lib/libiksolver.a COMLIB += $(NAN_OPENNL)/lib/$(DEBUG_DIR)libopennl.a COMLIB += $(NAN_SUPERLU)/lib/$(DEBUG_DIR)libsuperlu.a COMLIB += $(OCGDIR)/blender/avi/$(DEBUG_DIR)libavi.a @@ -227,8 +228,7 @@ ifeq ($(WITH_OPENEXR), true) COMLIB += $(NAN_OPENEXR_LIBS) endif -PULIB = $(NAN_IKSOLVER)/lib/libiksolver.a -PULIB += $(NAN_MOTO)/lib/libmoto.a +PULIB = $(NAN_MOTO)/lib/libmoto.a PULIB += $(NAN_ELBEEM)/lib/$(DEBUG_DIR)libelbeem.a PULIB += $(OCGDIR)/blender/readblenfile/$(DEBUG_DIR)libreadblenfile.a PULIB += $(OCGDIR)/blender/src/$(DEBUG_DIR)libsrcpublisher.a diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index 4b6cb5e0999..d7ef5cb54ff 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -216,30 +216,6 @@ struct EditEdge *findedgelist(struct EditVert *v1, struct EditVert *v2) { retur void countall(void) {} - -/* IKsolver stubs */ -#include "IK_solver.h" - -IK_Segment *IK_CreateSegment(int flag) { return 0; } -void IK_FreeSegment(IK_Segment *seg) {} - -void IK_SetParent(IK_Segment *seg, IK_Segment *parent) {} -void IK_SetTransform(IK_Segment *seg, float start[3], float rest_basis[][3], float basis[][3], float length) {} -void IK_GetBasisChange(IK_Segment *seg, float basis_change[][3]) {} -void IK_GetTranslationChange(IK_Segment *seg, float *translation_change) {}; -void IK_SetLimit(IK_Segment *seg, IK_SegmentAxis axis, float lower, float upper) {}; -void IK_SetStiffness(IK_Segment *seg, IK_SegmentAxis axis, float stiffness) {}; - -IK_Solver *IK_CreateSolver(IK_Segment *root) { return 0; } -void IK_FreeSolver(IK_Solver *solver) {}; - -void IK_SolverAddGoal(IK_Solver *solver, IK_Segment *tip, float goal[3], float weight) {} -void IK_SolverAddGoalOrientation(IK_Solver *solver, IK_Segment *tip, float goal[][3], float weight) {} -void IK_SolverSetPoleVectorConstraint(IK_Solver *solver, IK_Segment *tip, float goal[3], float polegoal[3], float poleangle, int getangle) {} -float IK_SolverGetPoleAngle(IK_Solver *solver) { return 0.0f; } - -int IK_Solve(IK_Solver *solver, float tolerance, int max_iterations) { return 0; } - /* exotic.c */ int BPY_call_importloader(char *name) { diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 04219ac5868..93cc0e8afb5 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -191,7 +191,7 @@ ADD_DEPENDENCIES(blender makesdna) FILE(READ ${CMAKE_BINARY_DIR}/cmake_blender_libs.txt BLENDER_LINK_LIBS) -SET(BLENDER_LINK_LIBS bf_nodes ${BLENDER_LINK_LIBS} src blender_python blender_render blender_radiosity blender_IK bf_elbeem) +SET(BLENDER_LINK_LIBS bf_nodes ${BLENDER_LINK_LIBS} src blender_python blender_render blender_radiosity bf_elbeem) IF(CMAKE_SYSTEM_NAME MATCHES "Linux") SET(BLENDER_LINK_LIBS ${BLENDER_LINK_LIBS} extern_binreloc) @@ -226,7 +226,7 @@ IF(UNIX) bf_decimation bf_elbeem bf_yafray - blender_IK + bf_IK bf_memutil bf_guardedalloc blender_CTR diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index b0950fece5f..a50577e2266 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -54,6 +54,7 @@ extern "C" #endif // __cplusplus #include "BKE_global.h" #include "BKE_icons.h" +#include "BKE_node.h" #include "BLI_blenlib.h" #include "DNA_scene_types.h" #include "BLO_readfile.h" @@ -376,6 +377,8 @@ int main(int argc, char** argv) ::DisposeNibReference(nibRef); */ #endif // __APPLE__ + + init_nodesystem(); GEN_init_messaging_system(); @@ -846,6 +849,8 @@ int main(int argc, char** argv) } } + free_nodesystem(); + if (pyGlobalDictString) { free(pyGlobalDictString); pyGlobalDictString = NULL; From 0f1a1a159ff70cd2bd9c1762ecd167439683b2ba Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 14 Sep 2008 04:32:17 +0000 Subject: [PATCH 056/125] == Keyframing - Cleanup of API == * Moved all keyframing functions to their own file (keyframing.c) * Merged all the different keyframing options (needed, visual, fast) into a single API call. The direct benefit of this is that it allows them to be used in conjunction with each other. Also, this means that when using the IKEY, autokeying settings for these are respected too. * Implemented 'keyingsets' system (instead of directly calling insertkey on relevant channels), which is easier to maintain and cleaner. A keyingset basically defines all the channels that can be keyframed together. This paves the way for custom keyingsets sometime down the track (and also for quick-insert keyframes for previously used keyingset). Menus for choosing the keying set to use are generated automatically from the definitions. --- source/blender/include/BIF_keyframing.h | 99 ++ source/blender/include/BSE_editipo.h | 9 +- source/blender/makesdna/DNA_action_types.h | 4 +- source/blender/python/api2_2x/Camera.c | 1 + source/blender/python/api2_2x/Constraint.c | 1 + source/blender/python/api2_2x/Ipo.c | 1 + source/blender/python/api2_2x/Ipocurve.c | 1 + source/blender/python/api2_2x/Lamp.c | 1 + source/blender/python/api2_2x/Material.c | 1 + source/blender/python/api2_2x/Object.c | 1 + source/blender/python/api2_2x/Pose.c | 1 + source/blender/python/api2_2x/World.c | 1 + source/blender/src/editaction.c | 1 + source/blender/src/editipo.c | 1291 +------------- source/blender/src/editmesh_add.c | 152 +- source/blender/src/editview.c | 1 + source/blender/src/header_view3d.c | 1 + source/blender/src/keyframing.c | 1767 ++++++++++++++++++++ source/blender/src/poselib.c | 2 +- source/blender/src/poseobject.c | 2 + source/blender/src/toets.c | 1 + source/blender/src/toolbox.c | 1 + source/blender/src/transform_conversions.c | 156 +- 23 files changed, 2100 insertions(+), 1396 deletions(-) create mode 100644 source/blender/include/BIF_keyframing.h create mode 100644 source/blender/src/keyframing.c diff --git a/source/blender/include/BIF_keyframing.h b/source/blender/include/BIF_keyframing.h new file mode 100644 index 00000000000..9ade4f74b92 --- /dev/null +++ b/source/blender/include/BIF_keyframing.h @@ -0,0 +1,99 @@ +/** + * $Id: BDR_gpencil.h 14444 2008*04*16 22:40:48Z aligorith $ + * + * ***** 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) 2008, Blender Foundation + * This is a new part of Blender (with some old code) + * + * Contributor(s): Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BIF_KEYFRAMING_H +#define BIF_KEYFRAMING_H + +struct ListBase; +struct ID; + +struct IpoCurve; +struct BezTriple; + +/* ************ Keyframing Management **************** */ + +/* Lesser Keyframing API call: + * Use this when validation of necessary animation data isn't necessary as it already + * exists, and there is a beztriple that can be directly copied into the array. + */ +int insert_bezt_icu(struct IpoCurve *icu, struct BezTriple *bezt); + +/* Main Keyframing API call: + * Use this when validation of necessary animation data isn't necessary as it + * already exists. It will insert a keyframe using the current value being keyframed. + */ +void insert_vert_icu(struct IpoCurve *icu, float x, float y, short flag); + + +/* flags for use in insert_key(), and insert_vert_icu() */ +enum { + INSERTKEY_NEEDED = (1<<0), /* only insert keyframes where they're needed */ + INSERTKEY_MATRIX = (1<<1), /* insert 'visual' keyframes where possible/needed */ + INSERTKEY_FAST = (1<<2), /* don't recalculate handles,etc. after adding key */ + INSERTKEY_FASTR = (1<<3), /* don't realloc mem (or increase count, as array has already been set out) */ + INSERTKEY_REPLACE = (1<<4), /* only replace an existing keyframe (this overrides INSERTKEY_NEEDED) */ +} eInsertKeyFlags; + +/* -------- */ + +/* Main Keyframing API calls: + * Use this to create any necessary animation data,, and then insert a keyframe + * using the current value being keyframed, in the relevant place. Returns success. + */ + // TODO: adapt this for new data-api -> this blocktype, etc. stuff is evil! +short insertkey(struct ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag); + +/* Main Keyframing API call: + * Use this to delete keyframe on current frame for relevant channel. Will perform checks just in case. + */ +short deletekey(struct ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag); + + +/* Main Keyframe Management calls: + * These handle keyframes management from various spaces. They will handle the menus + * required for each space. + */ +void common_insertkey(void); +void common_deletekey(void); + +/* ************ Keyframe Checking ******************** */ + +/* Checks whether a keyframe exists for the given ID-block one the given frame */ +short id_cfra_has_keyframe(struct ID *id, short filter); + +/* filter flags fr id_cfra_has_keyframe */ +enum { + /* general */ + ANIMFILTER_ALL = 0, /* include all available animation data */ + ANIMFILTER_LOCAL = (1<<0), /* only include locally available anim data */ + + /* object specific */ + ANIMFILTER_MAT = (1<<1), /* include material keyframes too */ + ANIMFILTER_SKEY = (1<<2), /* shape keys (for geometry) */ +} eAnimFilterFlags; + +#endif /* BIF_KEYFRAMING_H */ diff --git a/source/blender/include/BSE_editipo.h b/source/blender/include/BSE_editipo.h index e7445efc63e..b7b19a373aa 100644 --- a/source/blender/include/BSE_editipo.h +++ b/source/blender/include/BSE_editipo.h @@ -90,9 +90,6 @@ struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int struct Ipo *verify_ipo(struct ID *, short, char *, char *, char *); int texchannel_to_adrcode(int channel); -int insert_bezt_icu(struct IpoCurve *icu, struct BezTriple *bezt); -void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast); -void add_vert_ipo(void); void add_duplicate_editipo(void); void remove_doubles_ipo(void); @@ -121,10 +118,8 @@ void paste_editipo(void); void set_exprap_ipo(int mode); void set_speed_editipo(float speed); -void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, short fast); -void insertkey_smarter(ID *id, int blocktype, char *actname, char *constname, int adrcode); void insertkey_editipo(void); -void common_insertkey(void); +void add_vert_ipo(void); void free_ipokey(struct ListBase *lb); void add_to_ipokey(struct ListBase *lb, struct BezTriple *bezt, int nr, int len); void make_ipokey(void); @@ -163,8 +158,6 @@ void duplicate_ipo_keys(struct Ipo *ipo); void borderselect_ipo_key(struct Ipo *ipo, float xmin, float xmax, int val); void borderselect_icu_key(struct IpoCurve *icu, float xmin, float xmax, int (*select_function)(struct BezTriple *)); -int insertmatrixkey(ID *id, int blocktype, char *actname, char *constname, int adrcode); -void insertfloatkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, float floatkey); void select_ipo_key(struct Ipo *ipo, float selx, int sel); void select_icu_key(struct IpoCurve *icu, float selx, int selectmode); void setexprap_ipoloop(struct Ipo *ipo, int code); diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 2e8d95335cc..4a10ecf2368 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -277,7 +277,9 @@ typedef enum POSE_FLAG { /* clears the POSE_LOCKED flag for the next time the pose is evaluated */ POSE_DO_UNLOCK = (1<<2), /* pose has constraints which depend on time (used when depsgraph updates for a new frame) */ - POSE_CONSTRAINTS_TIMEDEPEND = (1<<3) + POSE_CONSTRAINTS_TIMEDEPEND = (1<<3), + /* recalculate bone paths */ + POSE_RECALCPATHS = (1<<4), } POSE_FLAG; /* PoseChannel (transform) flags */ diff --git a/source/blender/python/api2_2x/Camera.c b/source/blender/python/api2_2x/Camera.c index b35fcf410a4..87c605ef612 100644 --- a/source/blender/python/api2_2x/Camera.c +++ b/source/blender/python/api2_2x/Camera.c @@ -37,6 +37,7 @@ #include "BLI_blenlib.h" #include "BLI_arithb.h" /* for M_PI */ #include "BSE_editipo.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "mydevice.h" #include "gen_utils.h" diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c index a62a5ee7ed8..156d32d55c0 100644 --- a/source/blender/python/api2_2x/Constraint.c +++ b/source/blender/python/api2_2x/Constraint.c @@ -44,6 +44,7 @@ #include "BKE_constraint.h" #include "BLI_blenlib.h" #include "BIF_editconstraint.h" +#include "BIF_keyframing.h" #include "BIF_poseobject.h" #include "BSE_editipo.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/python/api2_2x/Ipo.c b/source/blender/python/api2_2x/Ipo.c index 68768fc9346..7c2e18bcdf6 100644 --- a/source/blender/python/api2_2x/Ipo.c +++ b/source/blender/python/api2_2x/Ipo.c @@ -36,6 +36,7 @@ #include "BKE_object.h" #include "BKE_ipo.h" #include "BLI_blenlib.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "BSE_editipo.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/python/api2_2x/Ipocurve.c b/source/blender/python/api2_2x/Ipocurve.c index b9bfb77d19e..4a8cba30e8e 100644 --- a/source/blender/python/api2_2x/Ipocurve.c +++ b/source/blender/python/api2_2x/Ipocurve.c @@ -35,6 +35,7 @@ #include "BKE_depsgraph.h" #include "BKE_ipo.h" #include "BKE_utildefines.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "BSE_editipo.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/python/api2_2x/Lamp.c b/source/blender/python/api2_2x/Lamp.c index 122c294001b..38968b64cf5 100644 --- a/source/blender/python/api2_2x/Lamp.c +++ b/source/blender/python/api2_2x/Lamp.c @@ -36,6 +36,7 @@ #include "BKE_library.h" #include "BKE_texture.h" #include "BLI_blenlib.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "BSE_editipo.h" #include "mydevice.h" diff --git a/source/blender/python/api2_2x/Material.c b/source/blender/python/api2_2x/Material.c index 842127650d7..b118bdb30e7 100644 --- a/source/blender/python/api2_2x/Material.c +++ b/source/blender/python/api2_2x/Material.c @@ -43,6 +43,7 @@ #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" #include "BSE_editipo.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "mydevice.h" #include "constant.h" diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index dc70921492c..a9cbd1c7766 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -81,6 +81,7 @@ struct rctf; #include "BIF_editarmature.h" #include "BIF_editaction.h" #include "BIF_editnla.h" +#include "BIF_keyframing.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" diff --git a/source/blender/python/api2_2x/Pose.c b/source/blender/python/api2_2x/Pose.c index 1021eac5fc4..52ede1cb3ee 100644 --- a/source/blender/python/api2_2x/Pose.c +++ b/source/blender/python/api2_2x/Pose.c @@ -43,6 +43,7 @@ #include "DNA_scene_types.h" #include "DNA_space_types.h" //1 - this order #include "BSE_editipo.h" //2 +#include "BIF_keyframing.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "Mathutils.h" diff --git a/source/blender/python/api2_2x/World.c b/source/blender/python/api2_2x/World.c index 09f7baed348..0c57488a266 100644 --- a/source/blender/python/api2_2x/World.c +++ b/source/blender/python/api2_2x/World.c @@ -50,6 +50,7 @@ #include "BKE_texture.h" #include "BLI_blenlib.h" #include "BSE_editipo.h" +#include "BIF_keyframing.h" #include "BIF_space.h" #include "mydevice.h" #include "Ipo.h" diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index c454715b1df..95a69171bf8 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -74,6 +74,7 @@ #include "BIF_editview.h" #include "BIF_gl.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_mywindow.h" #include "BIF_poseobject.h" #include "BIF_screen.h" diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index 5243b12535b..e6c7e155a0f 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -97,6 +97,7 @@ #include "BIF_editseq.h" #include "BIF_editview.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_mywindow.h" #include "BIF_poseobject.h" #include "BIF_screen.h" @@ -2021,185 +2022,6 @@ IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constn } -/* threshold for inserting keyframes - threshold here should be good enough for now, but should become userpref */ -#define BEZT_INSERT_THRESH 0.00001 - -/* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_icu) - * Returns the index to insert at (data already at that index will be offset if replace is 0) - */ -static int binarysearch_bezt_index (BezTriple array[], BezTriple *item, int arraylen, short *replace) -{ - int start=0, end=arraylen; - int loopbreaker= 0, maxloop= arraylen * 2; - const float frame= (item)? item->vec[1][0] : 0.0f; - - /* initialise replace-flag first */ - *replace= 0; - - /* sneaky optimisations (don't go through searching process if...): - * - keyframe to be added is to be added out of current bounds - * - keyframe to be added would replace one of the existing ones on bounds - */ - if ((arraylen <= 0) || ELEM(NULL, array, item)) { - printf("Warning: binarysearch_bezt_index encountered invalid array \n"); - return 0; - } - else { - /* check whether to add before/after/on */ - float framenum; - - /* 'First' Keyframe (when only one keyframe, this case is used) */ - framenum= array[0].vec[1][0]; - if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { - *replace = 1; - return 0; - } - else if (frame < framenum) - return 0; - - /* 'Last' Keyframe */ - framenum= array[(arraylen-1)].vec[1][0]; - if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { - *replace= 1; - return (arraylen - 1); - } - else if (frame > framenum) - return arraylen; - } - - - /* most of the time, this loop is just to find where to put it - * 'loopbreaker' is just here to prevent infinite loops - */ - for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) { - /* compute and get midpoint */ - int mid = (start + end) / 2; - float midfra= array[mid].vec[1][0]; - - /* check if exactly equal to midpoint */ - if (IS_EQT(frame, midfra, BEZT_INSERT_THRESH)) { - *replace = 1; - return mid; - } - - /* repeat in upper/lower half */ - if (frame > midfra) - start= mid + 1; - else if (frame < midfra) - end= mid - 1; - } - - /* print error if loop-limit exceeded */ - if (loopbreaker == (maxloop-1)) { - printf("Error: binarysearch_bezt_index was taking too long \n"); - - // include debug info - printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen); - } - - /* not found, so return where to place it */ - return start; -} - -/* This function adds a given BezTriple to an IPO-Curve. It will allocate - * memory for the array if needed, and will insert the BezTriple into a - * suitable place in chronological order. - * - * NOTE: any recalculate of the IPO-Curve that needs to be done will need to - * be done by the caller. - */ -int insert_bezt_icu (IpoCurve *icu, BezTriple *bezt) -{ - BezTriple *newb; - int i= 0; - - if (icu->bezt == NULL) { - icu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple"); - *(icu->bezt)= *bezt; - icu->totvert= 1; - } - else { - short replace = -1; - i = binarysearch_bezt_index(icu->bezt, bezt, icu->totvert, &replace); - - if (replace) { - /* sanity check: 'i' may in rare cases exceed arraylen */ - if ((i >= 0) && (i < icu->totvert)) - *(icu->bezt + i) = *bezt; - } - else { - /* add new */ - newb= MEM_callocN((icu->totvert+1)*sizeof(BezTriple), "beztriple"); - - /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */ - if (i > 0) - memcpy(newb, icu->bezt, i*sizeof(BezTriple)); - - /* add beztriple to paste at index i */ - *(newb + i)= *bezt; - - /* add the beztriples that occur after the beztriple to be pasted (originally in icu) */ - if (i < icu->totvert) - memcpy(newb+i+1, icu->bezt+i, (icu->totvert-i)*sizeof(BezTriple)); - - /* replace (+ free) old with new */ - MEM_freeN(icu->bezt); - icu->bezt= newb; - - icu->totvert++; - } - } - - /* we need to return the index, so that some tools which do post-processing can - * detect where we added the BezTriple in the array - */ - return i; -} - -/* This function is a wrapper for insert_bezt_icu, and should be used when - * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere - * else yet. - * - * 'fast' - is only for the python API where importing BVH's would take an extreamly long time. - */ -void insert_vert_icu (IpoCurve *icu, float x, float y, short fast) -{ - BezTriple beztr; - int a, h1, h2; - - /* set all three points, for nicer start position */ - memset(&beztr, 0, sizeof(BezTriple)); - beztr.vec[0][0]= x; - beztr.vec[0][1]= y; - beztr.vec[1][0]= x; - beztr.vec[1][1]= y; - beztr.vec[2][0]= x; - beztr.vec[2][1]= y; - beztr.hide= IPO_BEZ; - beztr.f1= beztr.f2= beztr.f3= SELECT; - beztr.h1= beztr.h2= HD_AUTO; - - /* add temp beztriple to keyframes */ - a= insert_bezt_icu(icu, &beztr); - if (!fast) calchandles_ipocurve(icu); - - /* set handletype */ - if (icu->totvert > 2) { - BezTriple *bezt; - - h1= h2= HD_AUTO; - bezt= (icu->bezt + a); - - if (a > 0) h1= (bezt-1)->h2; - if (a < icu->totvert-1) h2= (bezt+1)->h1; - - bezt->h1= h1; - bezt->h2= h2; - - if (!fast) calchandles_ipocurve(icu); - } -} - void add_vert_ipo(void) { EditIpo *ei; @@ -2259,525 +2081,6 @@ void add_vert_ipo(void) BIF_undo_push("Add Ipo vertex"); } -static void *get_context_ipo_poin(ID *id, int blocktype, char *actname, char *constname, IpoCurve *icu, int *vartype) -{ - if (blocktype==ID_PO) { - if (GS(id->name)==ID_OB) { - Object *ob= (Object *)id; - bPoseChannel *pchan= get_pose_channel(ob->pose, actname); - - if (pchan) { - *vartype= IPO_FLOAT; - return get_pchan_ipo_poin(pchan, icu->adrcode); - } - else - return NULL; - } - return NULL; - } - else if (blocktype==ID_CO) { - if ((GS(id->name)==ID_OB) && (constname && constname[0])) { - Object *ob= (Object *)id; - bConstraint *con; - - /* assume that we only want the influence (as only used for Constraint Channels) */ - if ((ob->ipoflag & OB_ACTION_OB) && !strcmp(actname, "Object")) { - for (con= ob->constraints.first; con; con= con->next) { - if (strcmp(constname, con->name)==0) { - *vartype= IPO_FLOAT; - return &con->enforce; - } - } - } - else if (ob->pose) { - bPoseChannel *pchan= get_pose_channel(ob->pose, actname); - - if (pchan) { - for (con= pchan->constraints.first; con; con= con->next) { - if (strcmp(constname, con->name)==0) { - *vartype= IPO_FLOAT; - return &con->enforce; - } - } - } - } - } - return NULL; - } - else - return get_ipo_poin(id, icu, vartype); - -} - -#define KEYNEEDED_DONTADD 0 -#define KEYNEEDED_JUSTADD 1 -#define KEYNEEDED_DELPREV 2 -#define KEYNEEDED_DELNEXT 3 - -static int new_key_needed(IpoCurve *icu, float cFrame, float nValue) -{ - /* This function determines whether a new keyframe is needed */ - /* Cases where keyframes should not be added: - * 1. Keyframe to be added bewteen two keyframes with similar values - * 2. Keyframe to be added on frame where two keyframes are already situated - * 3. Keyframe lies at point that intersects the linear line between two keyframes - */ - - BezTriple *bezt=NULL, *prev=NULL; - int totCount, i; - float valA = 0.0f, valB = 0.0f; - - /* safety checking */ - if (!icu) return KEYNEEDED_JUSTADD; - totCount= icu->totvert; - if (totCount==0) return KEYNEEDED_JUSTADD; - - /* loop through checking if any are the same */ - bezt= icu->bezt; - for (i=0; ivec[1][0]; - beztVal= bezt->vec[1][1]; - - if (prev) { - /* there is a keyframe before the one currently being examined */ - - /* get previous time+value */ - prevPosi= prev->vec[1][0]; - prevVal= prev->vec[1][1]; - - /* keyframe to be added at point where there are already two similar points? */ - if (IS_EQ(prevPosi, cFrame) && IS_EQ(beztPosi, cFrame) && IS_EQ(beztPosi, prevPosi)) { - return KEYNEEDED_DONTADD; - } - - /* keyframe between prev+current points ? */ - if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) { - /* is the value of keyframe to be added the same as keyframes on either side ? */ - if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) { - return KEYNEEDED_DONTADD; - } - else { - float realVal; - - /* get real value of curve at that point */ - realVal= eval_icu(icu, cFrame); - - /* compare whether it's the same as proposed */ - if (IS_EQ(realVal, nValue)) - return KEYNEEDED_DONTADD; - else - return KEYNEEDED_JUSTADD; - } - } - - /* new keyframe before prev beztriple? */ - if (cFrame < prevPosi) { - /* A new keyframe will be added. However, whether the previous beztriple - * stays around or not depends on whether the values of previous/current - * beztriples and new keyframe are the same. - */ - if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) - return KEYNEEDED_DELNEXT; - else - return KEYNEEDED_JUSTADD; - } - } - else { - /* just add a keyframe if there's only one keyframe - * and the new one occurs before the exisiting one does. - */ - if ((cFrame < beztPosi) && (totCount==1)) - return KEYNEEDED_JUSTADD; - } - - /* continue. frame to do not yet passed (or other conditions not met) */ - if (i < (totCount-1)) { - prev= bezt; - bezt++; - } - else - break; - } - - /* Frame in which to add a new-keyframe occurs after all other keys - * -> If there are at least two existing keyframes, then if the values of the - * last two keyframes and the new-keyframe match, the last existing keyframe - * gets deleted as it is no longer required. - * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last - * keyframe is not equal to last keyframe. - */ - bezt= (icu->bezt + (icu->totvert - 1)); - valA= bezt->vec[1][1]; - - if (prev) - valB= prev->vec[1][1]; - else - valB= bezt->vec[1][1] + 1.0f; - - if (IS_EQ(valA, nValue) && IS_EQ(valA, valB)) - return KEYNEEDED_DELPREV; - else - return KEYNEEDED_JUSTADD; -} - -/* a duplicate of insertkey that does not check for routing to insertmatrixkey - to avoid recursion problems */ -static void insertkey_nonrecurs(ID *id, int blocktype, char *actname, char *constname, int adrcode) -{ - IpoCurve *icu; - Object *ob; - void *poin= NULL; - float curval, cfra; - int vartype; - int matset=0; - - if (matset==0) { - icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); - - if(icu) { - - poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); - - if(poin) { - curval= read_ipo_poin(poin, vartype); - - cfra= frame_to_float(CFRA); - - /* if action is mapped in NLA, it returns a correction */ - if(actname && actname[0] && GS(id->name)==ID_OB) - cfra= get_action_frame((Object *)id, cfra); - - if( GS(id->name)==ID_OB ) { - ob= (Object *)id; - if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { - /* actually frametofloat calc again! */ - cfra-= give_timeoffset(ob)*G.scene->r.framelen; - } - } - - insert_vert_icu(icu, cfra, curval, 0); - } - } - } -} - -int insertmatrixkey(ID *id, int blocktype, char *actname, char *constname, int adrcode) -{ - int matindex=0; - /* branch on adrcode and blocktype, generating the proper matrix-based - values to send to insertfloatkey */ - if (GS(id->name)==ID_OB) { - Object *ob= (Object *)id; - - if ( blocktype==ID_OB ){ //working with an object - if ((ob)&&!(ob->parent)) { - if ((adrcode==OB_ROT_X)||(adrcode==OB_ROT_Y)||(adrcode==OB_ROT_Z)) { //get a rotation - float eul[3]; - switch (adrcode) { - case OB_ROT_X: - matindex=0; - break; - case OB_ROT_Y: - matindex=1; - break; - case OB_ROT_Z: - matindex=2; - break; - } - Mat4ToEul(ob->obmat, eul); - insertfloatkey(id, ID_OB, actname, NULL, adrcode, eul[matindex]*(5.72958)); - return 1; - } else if ((adrcode==OB_LOC_X)||(adrcode==OB_LOC_Y)||(adrcode==OB_LOC_Z)) {//get a translation - switch (adrcode) { - case OB_LOC_X: - matindex=0; - break; - case OB_LOC_Y: - matindex=1; - break; - case OB_LOC_Z: - matindex=2; - break; - } - insertfloatkey(id, ID_OB, actname, NULL, adrcode, ob->obmat[3][matindex]); - return 1; - } - } - } else if ( blocktype==ID_PO) { //working with a pose channel - bPoseChannel *pchan= get_pose_channel(ob->pose, actname); - if (pchan) { - if ((adrcode==AC_LOC_X)||(adrcode==AC_LOC_Y)||(adrcode==AC_LOC_Z)) { - switch (adrcode) { - case AC_LOC_X: - matindex=0; - break; - case AC_LOC_Y: - matindex=1; - break; - case AC_LOC_Z: - matindex=2; - break; - } - if (!(pchan->bone->parent)||((pchan->bone->parent)&&!(pchan->bone->flag&BONE_CONNECTED))) { /* don't use for non-connected child bones */ - float delta_mat[4][4]; - armature_mat_pose_to_delta(delta_mat, pchan->pose_mat, pchan->bone->arm_mat); - insertfloatkey(id, ID_PO, pchan->name, NULL, adrcode, delta_mat[3][matindex]); - return 1; - } - } else if ((adrcode==AC_QUAT_W)||(adrcode==AC_QUAT_X)||(adrcode==AC_QUAT_Y)||(adrcode==AC_QUAT_Z)) { - float tmat[4][4], trimat[3][3], localQuat[4]; - - switch (adrcode) { - case AC_QUAT_W: - matindex=0; - break; - case AC_QUAT_X: - matindex=1; - break; - case AC_QUAT_Y: - matindex=2; - break; - case AC_QUAT_Z: - matindex=3; - break; - } - - /* it should be reasonable to assume that we are keyframing on the active object, although it is not - * strictly required for this particular space conversion, arg1 must not be null for this to work - */ - Mat4CpyMat4(tmat, pchan->pose_mat); - constraint_mat_convertspace(OBACT, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); - - Mat3CpyMat4(trimat, tmat); - Mat3ToQuat_is_ok(trimat, localQuat); - insertfloatkey(id, ID_PO, pchan->name, NULL, adrcode, localQuat[matindex]); - - return 1; - } - } - } - } - /* failed to set a matrix key -- use traditional, but the non-recursing version */ - insertkey_nonrecurs(id,blocktype,actname,constname,adrcode); - return 0; -} - -static int match_adr_constraint(ID * id, int blocktype, char *actname, int adrcode) -{ /* This function matches constraint blocks with adrcodes to see if the - visual keying method should be used. For example, an object looking to key - location and having a CopyLoc constraint would return true. */ - - Object *ob=NULL; - int foundmatch=0; - int searchtype=0; - bConstraint *conref=NULL, *con=NULL; - - /*Retrieve constraint list*/ - if( GS(id->name)==ID_OB ) - ob= (Object *)id; - if (ob) { - if (blocktype==ID_PO) { - bPoseChannel *pchan= get_pose_channel(ob->pose, actname); - conref=pchan->constraints.first; - } else if (blocktype==ID_OB) { - conref=ob->constraints.first; - } - - if (conref) { - /*Set search type: 1 is for translation contraints, 2 is for rotation*/ - if ((adrcode==OB_LOC_X)||(adrcode==OB_LOC_Y)||(adrcode==OB_LOC_Z)||(adrcode==AC_LOC_X)||(adrcode==AC_LOC_Y)||(adrcode==AC_LOC_Z)) { - searchtype=1; - } else if ((adrcode==OB_ROT_X)||(adrcode==OB_ROT_Y)||(adrcode==OB_ROT_Z)||(adrcode==AC_QUAT_W)||(adrcode==AC_QUAT_X)||(adrcode==AC_QUAT_Y)||(adrcode==AC_QUAT_Z)) { - searchtype=2; - } - - if (searchtype>0) { - for (con=conref; (con)&&(foundmatch==0); con=con->next) { - switch (con->type) { - /* match constraint types to which kinds of keying they would affect */ - case CONSTRAINT_TYPE_CHILDOF: - foundmatch=1; - break; - case CONSTRAINT_TYPE_TRACKTO: - if (searchtype==2) foundmatch=1; - break; - case CONSTRAINT_TYPE_FOLLOWPATH: - foundmatch=1; - break; - case CONSTRAINT_TYPE_ROTLIMIT: - if (searchtype==2) foundmatch=1; - break; - case CONSTRAINT_TYPE_LOCLIMIT: - if (searchtype==1) foundmatch=1; - break; - case CONSTRAINT_TYPE_ROTLIKE: - if (searchtype==2) foundmatch=1; - break; - case CONSTRAINT_TYPE_LOCLIKE: - if (searchtype==1) foundmatch=1; - break; - case CONSTRAINT_TYPE_LOCKTRACK: - if (searchtype==2) foundmatch=1; - break; - case CONSTRAINT_TYPE_DISTLIMIT: - if (searchtype==1) foundmatch=1; - break; - case CONSTRAINT_TYPE_MINMAX: - if (searchtype==1) foundmatch=1; - break; - case CONSTRAINT_TYPE_TRANSFORM: - foundmatch=1; - break; - default: - break; - } - } - } - } - } - - return foundmatch; - -} - -void insertkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, short fast) -{ - IpoCurve *icu; - Object *ob; - void *poin= NULL; - float curval, cfra; - int vartype; - int matset=0; - - if ((IS_AUTOKEY_FLAG(AUTOMATKEY))&&(match_adr_constraint(id, blocktype, actname, adrcode))) { - matset=insertmatrixkey(id, blocktype, actname, constname, adrcode); - } - if (matset==0) { - icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); - - if(icu) { - - poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); - - if(poin) { - curval= read_ipo_poin(poin, vartype); - - cfra= frame_to_float(CFRA); - - /* if action is mapped in NLA, it returns a correction */ - if(actname && actname[0] && GS(id->name)==ID_OB) - cfra= get_action_frame((Object *)id, cfra); - - if( GS(id->name)==ID_OB ) { - ob= (Object *)id; - if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { - /* actually frametofloat calc again! */ - cfra-= give_timeoffset(ob)*G.scene->r.framelen; - } - } - - insert_vert_icu(icu, cfra, curval, fast); - } - } - } -} - - - -/* This function is a 'smarter' version of the insert key code. - * It uses an auxilliary function to check whether a keyframe is really needed */ -void insertkey_smarter(ID *id, int blocktype, char *actname, char *constname, int adrcode) -{ - IpoCurve *icu; - Object *ob; - void *poin= NULL; - float curval, cfra; - int vartype; - int insert_mode; - - icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); - - if(icu) { - - poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); - - if(poin) { - curval= read_ipo_poin(poin, vartype); - - cfra= frame_to_float(CFRA); - - /* if action is mapped in NLA, it returns a correction */ - if(actname && actname[0] && GS(id->name)==ID_OB) - cfra= get_action_frame((Object *)id, cfra); - - if( GS(id->name)==ID_OB ) { - ob= (Object *)id; - if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { - /* actually frametofloat calc again! */ - cfra-= give_timeoffset(ob)*G.scene->r.framelen; - } - } - - /* check whether this curve really needs a new keyframe */ - insert_mode= new_key_needed(icu, cfra, curval); - - /* insert new keyframe at current frame */ - if (insert_mode) - insert_vert_icu(icu, cfra, curval, 0); - - /* delete keyframe immediately before/after newly added */ - switch (insert_mode) { - case KEYNEEDED_DELPREV: - delete_icu_key(icu, icu->totvert-2, 1); - break; - case KEYNEEDED_DELNEXT: - delete_icu_key(icu, 1, 1); - break; - } - } - } -} - -/* For inserting keys based on an arbitrary float value */ -void insertfloatkey(ID *id, int blocktype, char *actname, char *constname, int adrcode, float floatkey) -{ - IpoCurve *icu; - Object *ob; - void *poin= NULL; - float cfra; - int vartype; - - icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); - - if(icu) { - - poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); - - if(poin) { - - cfra= frame_to_float(CFRA); - - /* if action is mapped in NLA, it returns a correction */ - if(actname && actname[0] && GS(id->name)==ID_OB) - cfra= get_action_frame((Object *)id, cfra); - - if( GS(id->name)==ID_OB ) { - ob= (Object *)id; - if((ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)!=0.0) ) { - /* actually frametofloat calc again! */ - cfra-= give_timeoffset(ob)*G.scene->r.framelen; - } - } - - /* insert new keyframe at current frame */ - insert_vert_icu(icu, cfra, floatkey, 0); - } - } -} void insertkey_editipo(void) { @@ -2909,598 +2212,6 @@ void insertkey_editipo(void) } -void common_insertkey(void) -{ - Base *base; - Object *ob; - Material *ma; - ID *id; - IpoCurve *icu; - World *wo; - Lamp *la; - Tex *te; - int tlay, map, event; - char menustr[256]; - - if(curarea->spacetype==SPACE_IPO) { - insertkey_editipo(); - } - else if(curarea->spacetype==SPACE_ACTION) { - insertkey_action(); - } - else if(curarea->spacetype==SPACE_BUTS) { - if(G.buts->mainb==CONTEXT_SHADING) { - int tab= G.buts->tab[CONTEXT_SHADING]; - - if(tab==TAB_SHADING_MAT) { - ma = G.buts->lockpoin; - ma = editnode_get_active_material(ma); - id = (ID *)ma; - - if(id) { - event= pupmenu("Insert Key %t|RGB%x0|Alpha%x1|Halo Size%x2|Mode %x3|All Color%x10|All Mirror%x14|Ofs%x12|Size%x13|All Mapping%x11"); - if(event== -1) return; - - map= texchannel_to_adrcode(ma->texact); - - if(event==0 || event==10) { - insertkey(id, ID_MA, NULL, NULL, MA_COL_R, 0); - insertkey(id, ID_MA, NULL, NULL, MA_COL_G, 0); - insertkey(id, ID_MA, NULL, NULL, MA_COL_B, 0); - } - if(event==1 || event==10) { - insertkey(id, ID_MA, NULL, NULL, MA_ALPHA, 0); - } - if(event==2 || event==10) { - insertkey(id, ID_MA, NULL, NULL, MA_HASIZE, 0); - } - if(event==3 || event==10) { - insertkey(id, ID_MA, NULL, NULL, MA_MODE, 0); - } - if(event==10) { - insertkey(id, ID_MA, NULL, NULL, MA_SPEC_R, 0); - insertkey(id, ID_MA, NULL, NULL, MA_SPEC_G, 0); - insertkey(id, ID_MA, NULL, NULL, MA_SPEC_B, 0); - insertkey(id, ID_MA, NULL, NULL, MA_REF, 0); - insertkey(id, ID_MA, NULL, NULL, MA_EMIT, 0); - insertkey(id, ID_MA, NULL, NULL, MA_AMB, 0); - insertkey(id, ID_MA, NULL, NULL, MA_SPEC, 0); - insertkey(id, ID_MA, NULL, NULL, MA_HARD, 0); - insertkey(id, ID_MA, NULL, NULL, MA_MODE, 0); - insertkey(id, ID_MA, NULL, NULL, MA_TRANSLU, 0); - insertkey(id, ID_MA, NULL, NULL, MA_ADD, 0); - } - if(event==14) { - insertkey(id, ID_MA, NULL, NULL, MA_RAYM, 0); - insertkey(id, ID_MA, NULL, NULL, MA_FRESMIR, 0); - insertkey(id, ID_MA, NULL, NULL, MA_FRESMIRI, 0); - insertkey(id, ID_MA, NULL, NULL, MA_FRESTRA, 0); - insertkey(id, ID_MA, NULL, NULL, MA_FRESTRAI, 0); - } - if(event==12 || event==11) { - insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_X, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_Y, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_OFS_Z, 0); - } - if(event==13 || event==11) { - insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_X, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_Y, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_SIZE_Z, 0); - } - if(event==11) { - insertkey(id, ID_MA, NULL, NULL, map+MAP_R, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_G, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_B, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_DVAR, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_COLF, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_NORF, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_VARF, 0); - insertkey(id, ID_MA, NULL, NULL, map+MAP_DISP, 0); - } - } - } - else if(tab==TAB_SHADING_WORLD) { - id= G.buts->lockpoin; - wo= G.buts->lockpoin; - if(id) { - event= pupmenu("Insert Key %t|Zenith RGB%x0|Horizon RGB%x1|Mist%x2|Stars %x3|Offset%x12|Size%x13"); - if(event== -1) return; - - map= texchannel_to_adrcode(wo->texact); - - if(event==0) { - insertkey(id, ID_WO, NULL, NULL, WO_ZEN_R, 0); - insertkey(id, ID_WO, NULL, NULL, WO_ZEN_G, 0); - insertkey(id, ID_WO, NULL, NULL, WO_ZEN_B, 0); - } - if(event==1) { - insertkey(id, ID_WO, NULL, NULL, WO_HOR_R, 0); - insertkey(id, ID_WO, NULL, NULL, WO_HOR_G, 0); - insertkey(id, ID_WO, NULL, NULL, WO_HOR_B, 0); - } - if(event==2) { - insertkey(id, ID_WO, NULL, NULL, WO_MISI, 0); - insertkey(id, ID_WO, NULL, NULL, WO_MISTDI, 0); - insertkey(id, ID_WO, NULL, NULL, WO_MISTSTA, 0); - insertkey(id, ID_WO, NULL, NULL, WO_MISTHI, 0); - } - if(event==3) { - insertkey(id, ID_WO, NULL, NULL, WO_STAR_R, 0); - insertkey(id, ID_WO, NULL, NULL, WO_STAR_G, 0); - insertkey(id, ID_WO, NULL, NULL, WO_STAR_B, 0); - insertkey(id, ID_WO, NULL, NULL, WO_STARDIST, 0); - insertkey(id, ID_WO, NULL, NULL, WO_STARSIZE, 0); - } - if(event==12) { - insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_X, 0); - insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_Y, 0); - insertkey(id, ID_WO, NULL, NULL, map+MAP_OFS_Z, 0); - } - if(event==13) { - insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_X, 0); - insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_Y, 0); - insertkey(id, ID_WO, NULL, NULL, map+MAP_SIZE_Z, 0); - } - } - } - else if(tab==TAB_SHADING_LAMP) { - id= G.buts->lockpoin; - la= G.buts->lockpoin; - if(id) { - event= pupmenu("Insert Key %t|RGB%x0|Energy%x1|Spot Size%x2|Offset%x12|Size%x13"); - if(event== -1) return; - - map= texchannel_to_adrcode(la->texact); - - if(event==0) { - insertkey(id, ID_LA, NULL, NULL, LA_COL_R, 0); - insertkey(id, ID_LA, NULL, NULL, LA_COL_G, 0); - insertkey(id, ID_LA, NULL, NULL, LA_COL_B, 0); - } - if(event==1) { - insertkey(id, ID_LA, NULL, NULL, LA_ENERGY, 0); - } - if(event==2) { - insertkey(id, ID_LA, NULL, NULL, LA_SPOTSI, 0); - } - if(event==12) { - insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_X, 0); - insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_Y, 0); - insertkey(id, ID_LA, NULL, NULL, map+MAP_OFS_Z, 0); - } - if(event==13) { - insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_X, 0); - insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_Y, 0); - insertkey(id, ID_LA, NULL, NULL, map+MAP_SIZE_Z, 0); - } - - } - } - else if(tab==TAB_SHADING_TEX) { - id= G.buts->lockpoin; - te= G.buts->lockpoin; - if(id) { - event= pupmenu("Insert Key %t|Clouds%x0|Marble%x1|Stucci%x2|Wood%x3|Magic%x4|Blend%x5|Musgrave%x6|Voronoi%x7|DistortedNoise%x8|ColorFilter%x9"); - if(event== -1) return; - - if(event==0) { - insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NTYPE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1, 0); - } - if(event==1) { - insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NTYPE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_TURB, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS2, 0); - } - if(event==2) { - insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NTYPE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_TURB, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1, 0); - } - if(event==3) { - insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NTYPE, 0); - insertkey(id, ID_TE, NULL, NULL, TE_TURB, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS1, 0); - insertkey(id, ID_TE, NULL, NULL, TE_N_BAS2, 0); - } - if(event==4) { - insertkey(id, ID_TE, NULL, NULL, TE_NDEPTH, 0); - insertkey(id, ID_TE, NULL, NULL, TE_TURB, 0); - } - if(event==5) { - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - } - if(event==6) { - insertkey(id, ID_TE, NULL, NULL, TE_MG_TYP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MGH, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_LAC, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_OCT, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_OFF, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_GAIN, 0); - } - if(event==7) { - insertkey(id, ID_TE, NULL, NULL, TE_VNW1, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VNW2, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VNW3, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VNW4, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VNMEXP, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VN_DISTM, 0); - insertkey(id, ID_TE, NULL, NULL, TE_VN_COLT, 0); - insertkey(id, ID_TE, NULL, NULL, TE_ISCA, 0); - insertkey(id, ID_TE, NULL, NULL, TE_NSIZE, 0); - } - if(event==8) { - insertkey(id, ID_TE, NULL, NULL, TE_MG_OCT, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_OFF, 0); - insertkey(id, ID_TE, NULL, NULL, TE_MG_GAIN, 0); - insertkey(id, ID_TE, NULL, NULL, TE_DISTA, 0); - } - if(event==9) { - insertkey(id, ID_TE, NULL, NULL, TE_COL_R, 0); - insertkey(id, ID_TE, NULL, NULL, TE_COL_G, 0); - insertkey(id, ID_TE, NULL, NULL, TE_COL_B, 0); - insertkey(id, ID_TE, NULL, NULL, TE_BRIGHT, 0); - insertkey(id, ID_TE, NULL, NULL, TE_CONTRA, 0); - } - } - } - } - else if(G.buts->mainb==CONTEXT_OBJECT) { - ob= OBACT; - if(ob) { - id= (ID *) (ob); - if(id) { - if(ob->type==OB_MESH) - event= pupmenu("Insert Key %t|Surface Damping%x0|Random Damping%x1|Permeability%x2|Force Strength%x3|Force Falloff%x4"); - else - event= pupmenu("Insert Key %t|Force Strength%x3|Force Falloff%x4"); - if(event == -1) return; - - if(event==0) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_SDAMP, 0); - } - if(event==1) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_RDAMP, 0); - } - if(event==2) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_PERM, 0); - } - if(event==3) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_FSTR, 0); - } - if(event==4) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_FFALL, 0); - } - if(event==5) { - insertkey(id, ID_OB, NULL, NULL, OB_PD_FMAXD, 0); - } - } - } - } - else if(G.buts->mainb==CONTEXT_EDITING) { - ob= OBACT; - if(ob && ob->type==OB_CAMERA) { - id= G.buts->lockpoin; - if(id) { - /* yafray: insert key extended with aperture and focal distance */ - /* qdn: FocalDistance now enabled for Blender as wel, for use with defocus node */ - if (G.scene->r.renderer==R_INTERN) - event= pupmenu("Insert Key %t|Lens%x0|Clipping%x1|FocalDistance%x3|Viewplane Shift%x4"); - else - event= pupmenu("Insert Key %t|Lens%x0|Clipping%x1|Aperture%x2|FocalDistance%x3"); - if(event== -1) return; - - if(event==0) { - insertkey(id, ID_CA, NULL, NULL, CAM_LENS, 0); - } - else if(event==1) { - insertkey(id, ID_CA, NULL, NULL, CAM_STA, 0); - insertkey(id, ID_CA, NULL, NULL, CAM_END, 0); - } - else if(event==2) { - insertkey(id, ID_CA, NULL, NULL, CAM_YF_APERT, 0); - } - else if(event==3) { - insertkey(id, ID_CA, NULL, NULL, CAM_YF_FDIST, 0); - } - else if(event==4) { - insertkey(id, ID_CA, NULL, NULL, CAM_SHIFT_X, 0); - insertkey(id, ID_CA, NULL, NULL, CAM_SHIFT_Y, 0); - } - } - } - } - else if(FALSE /* && G.buts->mainb==BUTS_SOUND */) { - if(G.ssound) { - id= G.buts->lockpoin; - if(id) { - event= pupmenu("Insert Key %t|Volume%x0|Pitch%x1|Panning%x2|Attennuation%x3"); - if(event== -1) return; - - if(event==0) { - insertkey(id, ID_SO, NULL, NULL, SND_VOLUME, 0); - } - if(event==1) { - insertkey(id, ID_SO, NULL, NULL, SND_PITCH, 0); - } - if(event==2) { - insertkey(id, ID_SO, NULL, NULL, SND_PANNING, 0); - } - if(event==3) { - insertkey(id, ID_SO, NULL, NULL, SND_ATTEN, 0); - } - } - } - } - - BIF_undo_push("Insert Key Buttons"); - - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - allqueue(REDRAWIPO, 0); - allspace(REMAKEIPO, 0); - - } - else if(curarea->spacetype==SPACE_VIEW3D) { - ob= OBACT; - - if (ob && (ob->flag & OB_POSEMODE)) { - bPoseChannel *pchan; - - set_pose_keys(ob); /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */ - for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) - if (pchan->flag & POSE_KEY) - break; - if(pchan==NULL) return; - strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Scale%x2|LocRot%x3|LocRotScale%x4|Avail%x9|Needed%x15|VisualLoc%x11|VisualRot%x12|VisualLocRot%x13"); - } - else { - base= FIRSTBASE; - while(base) { - if (TESTBASELIB(base)) break; - base= base->next; - } - if(base==NULL) return; - strcpy(menustr, "Insert Key%t|Loc%x0|Rot%x1|Scale%x2|LocRot%x3|LocRotScale%x4|Layer%x5|Avail%x9|Needed%x15|VisualLoc%x11|VisualRot%x12|VisualLocRot%x13"); - } - - if(ob) { - if(ob->type==OB_MESH) strcat(menustr, "| %x6|Mesh%x7"); - else if(ob->type==OB_LATTICE) strcat(menustr, "| %x6|Lattice%x7"); - else if(ob->type==OB_CURVE) strcat(menustr, "| %x6|Curve%x7"); - else if(ob->type==OB_SURF) strcat(menustr, "| %x6|Surface%x7"); - } - - event= pupmenu(menustr); - if(event== -1) return; - - if(event==7) { // ob != NULL - insert_shapekey(ob); - return; - } - - if (ob && (ob->flag & OB_POSEMODE)){ - bPoseChannel *pchan; - short recalc_bonepaths= 0; - - if (ob->action && ob->action->id.lib) { - error ("Can't key libactions"); - return; - } - - id= &ob->id; - for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) { - if (pchan->flag & POSE_KEY) { - /* insert relevant keyframes */ - if(event==0 || event==3 ||event==4) { - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); - } - if(event==1 || event==3 || event==4) { - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); - } - if(event==2 || event==4) { - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0); - } - if (event==9 && ob->action) { - bActionChannel *achan; - - for (achan = ob->action->chanbase.first; achan; achan=achan->next){ - if (achan->ipo && !strcmp (achan->name, pchan->name)){ - for (icu = achan->ipo->curve.first; icu; icu=icu->next){ - insertkey(id, ID_PO, achan->name, NULL, icu->adrcode, 0); - } - break; - } - } - } - if(event==11 || event==13) { - int matok=0; - /* check one to make sure we're not trying to set visual loc keys on - bones inside of a chain, which only leads to tears. */ - matok= insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_X); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z); - - if (matok == 0) { - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); - } - } - if(event==12 || event==13) { - int matok=0; - /* check one to make sure we're not trying to set visual rot keys on - bones inside of a chain, which only leads to tears. */ - matok= insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z); - - if (matok == 0) { - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); - } - } - if (event==15 && ob->action) { - bActionChannel *achan; - - for (achan = ob->action->chanbase.first; achan; achan=achan->next){ - if (achan->ipo && !strcmp (achan->name, pchan->name)){ - for (icu = achan->ipo->curve.first; icu; icu=icu->next){ - insertkey_smarter(id, ID_PO, achan->name, NULL, icu->adrcode); - } - break; - } - } - } - - /* clear unkeyed flag (it doesn't matter if it's set or not) */ - if (pchan->bone) - pchan->bone->flag &= ~BONE_UNKEYED; - - /* check if bone has a path */ - if (pchan->path) - recalc_bonepaths = 1; - } - } - - /* recalculate ipo handles, etc. */ - if(ob->action) - remake_action_ipos(ob->action); - - /* recalculate bone-paths on adding new keyframe? */ - // TODO: currently, there is no setting to turn this on/off globally - if (recalc_bonepaths) - pose_recalculate_paths(ob); - - - allqueue(REDRAWIPO, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - } - else { - base= FIRSTBASE; - while(base) { - if (TESTBASELIB(base)) { - char *actname= NULL; - - id= (ID *)(base->object); - - if(base->object->ipoflag & OB_ACTION_OB) - actname= "Object"; - - /* all curves in ipo deselect */ - if(base->object->ipo || base->object->action) { - if (base->object->ipo) { - icu= base->object->ipo->curve.first; - } - else { - bActionChannel *achan; - achan= get_action_channel(base->object->action, actname); - - if (achan && achan->ipo) - icu= achan->ipo->curve.first; - else - icu= NULL; - } - - while(icu) { - icu->flag &= ~IPO_SELECT; - - switch (event) { - case 9: - insertkey(id, ID_OB, actname, NULL, icu->adrcode, 0); - break; - case 15: - insertkey_smarter(id, ID_OB, actname, NULL, icu->adrcode); - break; - } - icu= icu->next; - } - } - - if(event==0 || event==3 ||event==4) { - insertkey(id, ID_OB, actname, NULL, OB_LOC_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_LOC_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_LOC_Z, 0); - } - if(event==1 || event==3 ||event==4) { - insertkey(id, ID_OB, actname, NULL, OB_ROT_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_ROT_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_ROT_Z, 0); - } - if(event==2 || event==4) { - insertkey(id, ID_OB, actname, NULL, OB_SIZE_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z, 0); - } - if(event==5) { - /* remove localview */ - tlay= base->object->lay; - base->object->lay &= 0xFFFFFF; - insertkey(id, ID_OB, actname, NULL, OB_LAY, 0); - base->object->lay= tlay; - } - if(event==11 || event==13) { - insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_X); - insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_Y); - insertmatrixkey(id, ID_OB, actname, NULL, OB_LOC_Z); - } - if(event==12 || event==13) { - insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_X); - insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_Y); - insertmatrixkey(id, ID_OB, actname, NULL, OB_ROT_Z); - } - base->object->recalc |= OB_RECALC_OB; - } - base= base->next; - } - } - - if(event==0) BIF_undo_push("Insert Loc Key"); - else if(event==1) BIF_undo_push("Insert Rot Key"); - else if(event==2) BIF_undo_push("Insert Scale Key"); - else if(event==3) BIF_undo_push("Insert LocRot Key"); - else if(event==4) BIF_undo_push("Insert LocRotScale Key"); - else if(event==5) BIF_undo_push("Insert Layer Key"); - else if(event==7) BIF_undo_push("Insert Vertex Key"); - else if(event==9) BIF_undo_push("Insert Avail Key"); - else if(event==11) BIF_undo_push("Insert VisualLoc Key"); - else if(event==12) BIF_undo_push("Insert VisualRot Key"); - else if(event==13) BIF_undo_push("Insert VisualLocRot Key"); - else if(event==15) BIF_undo_push("Insert Needed Key"); - - DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); - - allspace(REMAKEIPO, 0); - allqueue(REDRAWIPO, 0); - allqueue(REDRAWVIEW3D, 0); - allqueue(REDRAWACTION, 0); - allqueue(REDRAWNLA, 0); - } - -} - /* ****************************************************************************** */ void add_duplicate_editipo(void) diff --git a/source/blender/src/editmesh_add.c b/source/blender/src/editmesh_add.c index 9516f39b05c..71e04541643 100644 --- a/source/blender/src/editmesh_add.c +++ b/source/blender/src/editmesh_add.c @@ -869,6 +869,152 @@ int confirm_objectExists( Mesh **me, float mat[][3] ) return newob; } +// HACK: these can also be found in cmoview.tga.c, but are here so that they can be found by linker +// this hack is only used so that scons+mingw + split-sources hack works + // ------------------------------- start copied code +/* these are not the monkeys you are looking for */ +int monkeyo= 4; +int monkeynv= 271; +int monkeynf= 250; +signed char monkeyv[271][3]= { +{-71,21,98},{-63,12,88},{-57,7,74},{-82,-3,79},{-82,4,92}, +{-82,17,100},{-92,21,102},{-101,12,95},{-107,7,83}, +{-117,31,84},{-109,31,95},{-96,31,102},{-92,42,102}, +{-101,50,95},{-107,56,83},{-82,66,79},{-82,58,92}, +{-82,46,100},{-71,42,98},{-63,50,88},{-57,56,74}, +{-47,31,72},{-55,31,86},{-67,31,97},{-66,31,99}, +{-70,43,100},{-82,48,103},{-93,43,105},{-98,31,105}, +{-93,20,105},{-82,31,106},{-82,15,103},{-70,20,100}, +{-127,55,95},{-127,45,105},{-127,-87,94},{-127,-41,100}, +{-127,-24,102},{-127,-99,92},{-127,52,77},{-127,73,73}, +{-127,115,-70},{-127,72,-109},{-127,9,-106},{-127,-49,-45}, +{-101,-24,72},{-87,-56,73},{-82,-89,73},{-80,-114,68}, +{-85,-121,67},{-104,-124,71},{-127,-126,74},{-71,-18,68}, +{-46,-5,69},{-21,19,57},{-17,55,76},{-36,62,80}, +{-64,77,88},{-86,97,94},{-107,92,97},{-119,63,96}, +{-106,53,99},{-111,39,98},{-101,12,95},{-79,2,90}, +{-64,8,86},{-47,24,83},{-45,38,83},{-50,48,85}, +{-72,56,92},{-95,60,97},{-127,-98,94},{-113,-92,94}, +{-112,-107,91},{-119,-113,89},{-127,-114,88},{-127,-25,96}, +{-127,-18,95},{-114,-19,95},{-111,-29,96},{-116,-37,95}, +{-76,-6,86},{-48,7,80},{-34,26,77},{-32,48,84}, +{-39,53,93},{-71,70,102},{-87,82,107},{-101,79,109}, +{-114,55,108},{-111,-13,104},{-100,-57,91},{-95,-90,88}, +{-93,-105,85},{-97,-117,81},{-106,-119,81},{-127,-121,82}, +{-127,6,93},{-127,27,98},{-85,61,95},{-106,18,96}, +{-110,27,97},{-112,-88,94},{-117,-57,96},{-127,-57,96}, +{-127,-42,95},{-115,-35,100},{-110,-29,102},{-113,-17,100}, +{-122,-16,100},{-127,-26,106},{-121,-19,104},{-115,-20,104}, +{-113,-29,106},{-117,-32,103},{-127,-37,103},{-94,-40,71}, +{-106,-31,91},{-104,-40,91},{-97,-32,71},{-127,-112,88}, +{-121,-111,88},{-115,-105,91},{-115,-95,93},{-127,-100,84}, +{-115,-96,85},{-115,-104,82},{-121,-109,81},{-127,-110,81}, +{-105,28,100},{-103,20,99},{-84,55,97},{-92,54,99}, +{-73,51,99},{-55,45,89},{-52,37,88},{-53,25,87}, +{-66,13,92},{-79,8,95},{-98,14,100},{-104,38,100}, +{-100,48,100},{-97,46,97},{-102,38,97},{-96,16,97}, +{-79,11,93},{-68,15,90},{-57,27,86},{-56,36,86}, +{-59,43,87},{-74,50,96},{-91,51,98},{-84,52,96}, +{-101,22,96},{-102,29,96},{-113,59,78},{-102,85,79}, +{-84,88,76},{-65,71,71},{-40,58,63},{-25,52,59}, +{-28,21,48},{-50,0,53},{-71,-12,60},{-127,115,37}, +{-127,126,-10},{-127,-25,-86},{-127,-59,24},{-127,-125,59}, +{-127,-103,44},{-127,-73,41},{-127,-62,36},{-18,30,7}, +{-17,41,-6},{-28,34,-56},{-68,56,-90},{-33,-6,9}, +{-51,-16,-21},{-45,-1,-55},{-84,7,-85},{-97,-45,52}, +{-104,-53,33},{-90,-91,49},{-95,-64,50},{-85,-117,51}, +{-109,-97,47},{-111,-69,46},{-106,-121,56},{-99,-36,55}, +{-100,-29,60},{-101,-22,64},{-100,-50,21},{-89,-40,-34}, +{-83,-19,-69},{-69,111,-49},{-69,119,-9},{-69,109,30}, +{-68,67,55},{-34,52,43},{-46,58,36},{-45,90,7}, +{-25,72,16},{-25,79,-15},{-45,96,-25},{-45,87,-57}, +{-25,69,-46},{-48,42,-75},{-65,3,-70},{-22,42,-26}, +{-75,-22,19},{-72,-25,-27},{-13,52,-30},{-28,-18,-16}, +{6,-13,-42},{37,7,-55},{46,41,-54},{31,65,-54}, +{4,61,-40},{3,53,-37},{25,56,-50},{35,37,-52}, +{28,10,-52},{5,-5,-39},{-21,-9,-17},{-9,46,-28}, +{-6,39,-37},{-14,-3,-27},{6,0,-47},{25,12,-57}, +{31,32,-57},{23,46,-56},{4,44,-46},{-19,37,-27}, +{-20,22,-35},{-30,12,-35},{-22,11,-35},{-19,2,-35}, +{-23,-2,-35},{-34,0,-9},{-35,-3,-22},{-35,5,-24}, +{-25,26,-27},{-13,31,-34},{-13,30,-41},{-23,-2,-41}, +{-18,2,-41},{-21,10,-41},{-29,12,-41},{-19,22,-41}, +{6,42,-53},{25,44,-62},{34,31,-63},{28,11,-62}, +{7,0,-54},{-14,-2,-34},{-5,37,-44},{-13,14,-42}, +{-7,8,-43},{1,16,-47},{-4,22,-45},{3,30,-48}, +{8,24,-49},{15,27,-50},{12,35,-50},{4,56,-62}, +{33,60,-70},{48,38,-64},{41,7,-68},{6,-11,-63}, +{-26,-16,-42},{-17,49,-49}, +}; + +signed char monkeyf[250][4]= { +{27,4,5,26}, {25,4,5,24}, {3,6,5,4}, {1,6,5,2}, {5,6,7,4}, +{3,6,7,2}, {5,8,7,6}, {3,8,7,4}, {7,8,9,6}, +{5,8,9,4}, {7,10,9,8}, {5,10,9,6}, {9,10,11,8}, +{7,10,11,6}, {9,12,11,10}, {7,12,11,8}, {11,6,13,12}, +{5,4,13,12}, {3,-2,13,12}, {-3,-4,13,12}, {-5,-10,13,12}, +{-11,-12,14,12}, {-13,-18,14,13}, {-19,4,5,13}, {10,12,4,4}, +{10,11,9,9}, {8,7,9,9}, {7,5,6,6}, {6,3,4,4}, +{5,1,2,2}, {4,-1,0,0}, {3,-3,-2,-2}, {22,67,68,23}, +{20,65,66,21}, {18,63,64,19}, {16,61,62,17}, {14,59,60,15}, +{12,19,48,57}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, +{18,19,48,47}, {18,19,48,47}, {18,19,48,47}, {18,19,48,47}, +{18,19,48,47}, {18,-9,-8,47}, {18,27,45,46}, {26,55,43,44}, +{24,41,42,54}, {22,39,40,23}, {20,37,38,21}, {18,35,36,19}, +{16,33,34,17}, {14,31,32,15}, {12,39,30,13}, {11,48,45,38}, +{8,36,-19,9}, {8,-20,44,47}, {42,45,46,43}, {18,19,40,39}, +{16,17,38,37}, {14,15,36,35}, {32,44,43,33}, {12,33,32,42}, +{19,44,43,42}, {40,41,42,-27}, {8,9,39,-28}, {15,43,42,16}, +{13,43,42,14}, {11,43,42,12}, {9,-30,42,10}, {37,12,38,-32}, +{-33,37,45,46}, {-33,40,41,39}, {38,40,41,37}, {36,40,41,35}, +{34,40,41,33}, {36,39,38,37}, {35,40,39,38}, {1,2,14,21}, +{1,2,40,13}, {1,2,40,39}, {1,24,12,39}, {-34,36,38,11}, +{35,38,36,37}, {-37,8,35,37}, {-11,-12,-45,40}, {-11,-12,39,38}, +{-11,-12,37,36}, {-11,-12,35,34}, {33,34,40,41}, {33,34,38,39}, +{33,34,36,37}, {33,-52,34,35}, {33,37,36,34}, {33,35,34,34}, +{8,7,37,36}, {-32,7,35,46}, {-34,-33,45,46}, {4,-33,43,34}, +{-34,-33,41,42}, {-34,-33,39,40}, {-34,-33,37,38}, {-34,-33,35,36}, +{-34,-33,33,34}, {-34,-33,31,32}, {-34,-4,28,30}, {-5,-34,28,27}, +{-35,-44,36,27}, {26,35,36,45}, {24,25,44,45}, {25,23,44,42}, +{25,24,41,40}, {25,24,39,38}, {25,24,37,36}, {25,24,35,34}, +{25,24,33,32}, {25,24,31,30}, {15,24,29,38}, {25,24,27,26}, +{23,12,37,26}, {11,12,35,36}, {-86,-59,36,-80}, {-60,-61,36,35}, +{-62,-63,36,35}, {-64,-65,36,35}, {-66,-67,36,35}, {-68,-69,36,35}, +{-70,-71,36,35}, {-72,-73,36,35}, {-74,-75,36,35}, {42,43,53,58}, +{40,41,57,56}, {38,39,55,57}, {-81,-80,37,56}, {-83,-82,55,52}, +{-85,-84,51,49}, {-87,-86,48,49}, {47,50,51,48}, {46,48,51,49}, +{43,46,49,44}, {-92,-91,45,42}, {-23,49,50,-20}, {-94,40,48,-24}, +{-96,-22,48,49}, {-97,48,21,-90}, {-100,36,50,23}, {22,49,48,-100}, +{-101,47,46,22}, {21,45,35,25}, {33,34,44,41}, {13,14,28,24}, +{-107,26,30,-106}, {14,46,45,15}, {14,44,43,-110}, {-111,42,23,-110}, +{6,7,45,46}, {45,44,47,46}, {45,46,47,48}, {47,46,49,48}, +{17,49,47,48}, {17,36,46,48}, {35,36,44,45}, {35,36,40,43}, +{35,36,38,39}, {-4,-3,37,35}, {-123,34,33,1}, {-9,-8,-7,-6}, +{-10,-7,32,-125}, {-127,-11,-126,-126}, {-7,-6,5,31}, {4,5,33,30}, +{4,39,33,32}, {4,35,32,38}, {20,21,39,38}, {4,37,38,5}, +{-11,-10,36,3}, {-11,15,14,35}, {13,16,34,34}, {-13,14,13,13}, +{-3,1,30,29}, {-3,28,29,1}, {-2,31,28,-1}, {12,13,27,30}, +{-2,26,12,12}, {35,29,42,36}, {34,35,36,33}, {32,35,36,31}, +{30,35,36,29}, {28,35,36,27}, {26,35,36,25}, {34,39,38,35}, +{32,39,38,33}, {30,39,38,31}, {28,39,38,29}, {26,39,38,27}, +{25,31,32,38}, {-18,-17,45,44}, {-18,17,28,44}, {-24,-20,42,-23}, +{11,35,27,14}, {25,28,39,41}, {37,41,40,38}, {34,40,36,35}, +{32,40,39,33}, {30,39,31,40}, {21,29,39,22}, {-31,37,28,4}, +{-32,33,35,36}, {32,33,34,34}, {18,35,36,48}, {34,25,40,35}, +{24,25,38,39}, {24,25,36,37}, {24,25,34,35}, {24,25,32,33}, +{24,13,41,31}, {17,11,41,35}, {15,16,34,35}, {13,14,34,35}, +{11,12,34,35}, {9,10,34,35}, {7,8,34,35}, {26,25,37,36}, +{35,36,37,38}, {37,36,39,38}, {37,38,39,40}, {25,31,36,39}, +{18,34,35,30}, {17,22,30,33}, {19,29,21,20}, {16,26,29,17}, +{24,29,28,25}, {22,31,28,23}, {20,31,30,21}, {18,31,30,19}, +{16,30,17,17}, {-21,-22,35,34}, {-21,-22,33,32}, {-21,-22,31,30}, +{-21,-22,29,28}, {-21,-22,27,26}, {-28,-22,25,31}, {24,28,29,30}, +{23,24,26,27}, {23,24,25,25}, {-69,-35,-32,27}, {-70,26,25,-66}, +{-68,-67,24,-33}, +}; + // ------------------------------- end copied code + + void make_prim(int type, float imat[3][3], int tot, int seg, int subdiv, float dia, float d, int ext, int fill, float cent[3]) @@ -1022,9 +1168,9 @@ void make_prim(int type, float imat[3][3], int tot, int seg, break; case 13: /* Monkey */ { - extern int monkeyo, monkeynv, monkeynf; - extern signed char monkeyf[][4]; - extern signed char monkeyv[][3]; + //extern int monkeyo, monkeynv, monkeynf; + //extern signed char monkeyf[][4]; + //extern signed char monkeyv[][3]; EditVert **tv= MEM_mallocN(sizeof(*tv)*monkeynv*2, "tv"); EditFace *efa; int i; diff --git a/source/blender/src/editview.c b/source/blender/src/editview.c index 2133a92a54e..f95b56fe5b0 100644 --- a/source/blender/src/editview.c +++ b/source/blender/src/editview.c @@ -89,6 +89,7 @@ #include "BIF_gl.h" #include "BIF_glutil.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_mywindow.h" #include "BIF_previewrender.h" /* use only so fly mode can preview when its done */ #include "BIF_space.h" diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index 704d4bdea54..acd80f5efdd 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -106,6 +106,7 @@ #include "BIF_editview.h" #include "BIF_gl.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_mainqueue.h" #include "BIF_meshtools.h" #include "BIF_poselib.h" diff --git a/source/blender/src/keyframing.c b/source/blender/src/keyframing.c new file mode 100644 index 00000000000..b2fad5e85ce --- /dev/null +++ b/source/blender/src/keyframing.c @@ -0,0 +1,1767 @@ +/** + * $Id: keyframing.c 14881 2008-05-18 10:41:42Z aligorith $ + * + * ***** 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) 2008, Blender Foundation + * This is a new part of Blender (with some old code) + * + * Contributor(s): Joshua Leung + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "MEM_guardedalloc.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" +#include "BLI_dynstr.h" + +#include "DNA_listBase.h" +#include "DNA_ID.h" +#include "DNA_action_types.h" +#include "DNA_armature_types.h" +#include "DNA_camera_types.h" +#include "DNA_constraint_types.h" +#include "DNA_curve_types.h" +#include "DNA_ipo_types.h" +#include "DNA_lamp_types.h" +#include "DNA_object_types.h" +#include "DNA_material_types.h" +#include "DNA_screen_types.h" +#include "DNA_scene_types.h" +#include "DNA_space_types.h" +#include "DNA_texture_types.h" +#include "DNA_userdef_types.h" +#include "DNA_vec_types.h" +#include "DNA_view3d_types.h" +#include "DNA_world_types.h" + +#include "BKE_global.h" +#include "BKE_utildefines.h" +#include "BKE_blender.h" +#include "BKE_main.h" +#include "BKE_action.h" +#include "BKE_armature.h" +#include "BKE_constraint.h" +#include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_ipo.h" +#include "BKE_object.h" + +#include "BIF_keyframing.h" +#include "BIF_butspace.h" +#include "BIF_editaction.h" +#include "BIF_editkey.h" +#include "BIF_interface.h" +#include "BIF_mywindow.h" +#include "BIF_poseobject.h" +#include "BIF_screen.h" +#include "BIF_space.h" +#include "BIF_toolbox.h" +#include "BIF_toets.h" + +#include "BSE_editipo.h" +#include "BSE_node.h" +#include "BSE_time.h" +#include "BSE_view.h" + +#include "blendef.h" + +#include "PIL_time.h" /* sleep */ +#include "mydevice.h" + +/* ************************************************** */ +/* LOCAL TYPES AND DEFINES */ + +/* -------------- Keying Sets ------------------- */ + +/* keying set - a set of channels that will be keyframed together */ +// TODO: move this to a header to allow custom sets someday? +typedef struct bKeyingSet { + /* callback func to consider if keyingset should be included + * (by default, if this is undefined, item will be shown) + */ + short (*include_cb)(struct bKeyingSet *, const char *); + + char name[48]; /* name of keyingset */ + int blocktype; /* blocktype that all channels belong to */ // in future, this may be eliminated + short flag; /* flags to use when setting keyframes */ + + short chan_num; /* number of channels to insert keyframe in */ + short adrcodes[32]; /* adrcodes for channels to insert keys for (ideally would be variable-len, but limit of 32 will suffice) */ +} bKeyingSet; + +/* keying set context - an array of keying sets and the number of them */ +typedef struct bKeyingContext { + bKeyingSet *keyingsets; /* array containing the keyingsets of interest */ + bKeyingSet *lastused; /* item that was chosen last time*/ + int tot; /* number of keyingsets in */ +} bKeyingContext; + + +/* ----------- Common KeyData Sources ------------ */ + +/* temporary struct to gather data combos to keyframe */ +typedef struct bCommonKeySrc { + struct bCommonKeySrc *next, *prev; + + /* general data/destination-source settings */ + ID *id; /* id-block this comes from */ + char *actname; /* name of action channel */ + char *constname; /* name of constraint channel */ + + /* general destination source settings */ + Ipo *ipo; /* ipo-block that id-block has (optional) */ + bAction *act; /* action-block that id-block has (optional) */ + + /* pose-level settings */ + bPoseChannel *pchan; /* pose channel */ + + /* buttons-window settings */ + int map; /* offset to apply to certain adrcodes */ +} bCommonKeySrc; + +/* ************************************************** */ +/* KEYFRAME INSERTION */ + +/* -------------- BezTriple Insertion -------------------- */ + +/* threshold for inserting keyframes - threshold here should be good enough for now, but should become userpref */ +#define BEZT_INSERT_THRESH 0.00001 + +/* Binary search algorithm for finding where to insert BezTriple. (for use by insert_bezt_icu) + * Returns the index to insert at (data already at that index will be offset if replace is 0) + */ +static int binarysearch_bezt_index (BezTriple array[], BezTriple *item, int arraylen, short *replace) +{ + int start=0, end=arraylen; + int loopbreaker= 0, maxloop= arraylen * 2; + const float frame= (item)? item->vec[1][0] : 0.0f; + + /* initialise replace-flag first */ + *replace= 0; + + /* sneaky optimisations (don't go through searching process if...): + * - keyframe to be added is to be added out of current bounds + * - keyframe to be added would replace one of the existing ones on bounds + */ + if ((arraylen <= 0) || ELEM(NULL, array, item)) { + printf("Warning: binarysearch_bezt_index encountered invalid array \n"); + return 0; + } + else { + /* check whether to add before/after/on */ + float framenum; + + /* 'First' Keyframe (when only one keyframe, this case is used) */ + framenum= array[0].vec[1][0]; + if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { + *replace = 1; + return 0; + } + else if (frame < framenum) + return 0; + + /* 'Last' Keyframe */ + framenum= array[(arraylen-1)].vec[1][0]; + if (IS_EQT(frame, framenum, BEZT_INSERT_THRESH)) { + *replace= 1; + return (arraylen - 1); + } + else if (frame > framenum) + return arraylen; + } + + + /* most of the time, this loop is just to find where to put it + * 'loopbreaker' is just here to prevent infinite loops + */ + for (loopbreaker=0; (start <= end) && (loopbreaker < maxloop); loopbreaker++) { + /* compute and get midpoint */ + int mid = (start + end) / 2; + float midfra= array[mid].vec[1][0]; + + /* check if exactly equal to midpoint */ + if (IS_EQT(frame, midfra, BEZT_INSERT_THRESH)) { + *replace = 1; + return mid; + } + + /* repeat in upper/lower half */ + if (frame > midfra) + start= mid + 1; + else if (frame < midfra) + end= mid - 1; + } + + /* print error if loop-limit exceeded */ + if (loopbreaker == (maxloop-1)) { + printf("Error: binarysearch_bezt_index was taking too long \n"); + + // include debug info + printf("\tround = %d: start = %d, end = %d, arraylen = %d \n", loopbreaker, start, end, arraylen); + } + + /* not found, so return where to place it */ + return start; +} + +/* This function adds a given BezTriple to an IPO-Curve. It will allocate + * memory for the array if needed, and will insert the BezTriple into a + * suitable place in chronological order. + * + * NOTE: any recalculate of the IPO-Curve that needs to be done will need to + * be done by the caller. + */ +int insert_bezt_icu (IpoCurve *icu, BezTriple *bezt) +{ + BezTriple *newb; + int i= 0; + + if (icu->bezt == NULL) { + icu->bezt= MEM_callocN(sizeof(BezTriple), "beztriple"); + *(icu->bezt)= *bezt; + icu->totvert= 1; + } + else { + short replace = -1; + i = binarysearch_bezt_index(icu->bezt, bezt, icu->totvert, &replace); + + if (replace) { + /* sanity check: 'i' may in rare cases exceed arraylen */ + if ((i >= 0) && (i < icu->totvert)) + *(icu->bezt + i) = *bezt; + } + else { + /* add new */ + newb= MEM_callocN((icu->totvert+1)*sizeof(BezTriple), "beztriple"); + + /* add the beztriples that should occur before the beztriple to be pasted (originally in ei->icu) */ + if (i > 0) + memcpy(newb, icu->bezt, i*sizeof(BezTriple)); + + /* add beztriple to paste at index i */ + *(newb + i)= *bezt; + + /* add the beztriples that occur after the beztriple to be pasted (originally in icu) */ + if (i < icu->totvert) + memcpy(newb+i+1, icu->bezt+i, (icu->totvert-i)*sizeof(BezTriple)); + + /* replace (+ free) old with new */ + MEM_freeN(icu->bezt); + icu->bezt= newb; + + icu->totvert++; + } + } + + /* we need to return the index, so that some tools which do post-processing can + * detect where we added the BezTriple in the array + */ + return i; +} + +/* This function is a wrapper for insert_bezt_icu, and should be used when + * adding a new keyframe to a curve, when the keyframe doesn't exist anywhere + * else yet. + * + * 'fast' - is only for the python API where importing BVH's would take an extreamly long time. + */ +void insert_vert_icu (IpoCurve *icu, float x, float y, short fast) +{ + BezTriple beztr; + int a, h1, h2; + + /* set all three points, for nicer start position */ + memset(&beztr, 0, sizeof(BezTriple)); + beztr.vec[0][0]= x; + beztr.vec[0][1]= y; + beztr.vec[1][0]= x; + beztr.vec[1][1]= y; + beztr.vec[2][0]= x; + beztr.vec[2][1]= y; + beztr.hide= IPO_BEZ; + beztr.f1= beztr.f2= beztr.f3= SELECT; + beztr.h1= beztr.h2= HD_AUTO; + + /* add temp beztriple to keyframes */ + a= insert_bezt_icu(icu, &beztr); + if (!fast) calchandles_ipocurve(icu); + + /* set handletype */ + if (icu->totvert > 2) { + BezTriple *bezt; + + h1= h2= HD_AUTO; + bezt= (icu->bezt + a); + + if (a > 0) h1= (bezt-1)->h2; + if (a < icu->totvert-1) h2= (bezt+1)->h1; + + bezt->h1= h1; + bezt->h2= h2; + + if (!fast) calchandles_ipocurve(icu); + } +} + +/* ------------------- Get Data ------------------------ */ + +/* Get pointer to use to get values from */ +// FIXME: this should not be possible with Data-API +static void *get_context_ipo_poin(ID *id, int blocktype, char *actname, char *constname, IpoCurve *icu, int *vartype) +{ + switch (blocktype) { + case ID_PO: /* posechannel */ + if (GS(id->name)==ID_OB) { + Object *ob= (Object *)id; + bPoseChannel *pchan= get_pose_channel(ob->pose, actname); + + if (pchan) { + *vartype= IPO_FLOAT; + return get_pchan_ipo_poin(pchan, icu->adrcode); + } + } + break; + + case ID_CO: /* constraint */ + if ((GS(id->name)==ID_OB) && (constname && constname[0])) { + Object *ob= (Object *)id; + bConstraint *con; + + /* assume that we only want the influence (as only used for Constraint Channels) */ + if ((ob->ipoflag & OB_ACTION_OB) && !strcmp(actname, "Object")) { + for (con= ob->constraints.first; con; con= con->next) { + if (strcmp(constname, con->name)==0) { + *vartype= IPO_FLOAT; + return &con->enforce; + } + } + } + else if (ob->pose) { + bPoseChannel *pchan= get_pose_channel(ob->pose, actname); + + if (pchan) { + for (con= pchan->constraints.first; con; con= con->next) { + if (strcmp(constname, con->name)==0) { + *vartype= IPO_FLOAT; + return &con->enforce; + } + } + } + } + } + break; + + case ID_OB: /* object */ + /* hack: layer channels for object need to be keyed WITHOUT localview flag... + * tsk... tsk... why must we just dump bitflags upon users :/ + */ + if ((GS(id->name)==ID_OB) && (icu->adrcode==OB_LAY)) { + Object *ob= (Object *)id; + static int layer = 0; + + /* init layer to be the object's layer var, then remove local view from it */ + layer = ob->lay; + layer &= 0xFFFFFF; + + /* return pointer to this static var + * - assumes that this pointer won't be stored for use later, so may not be threadsafe + * if multiple keyframe calls are made, but that is unlikely to happen in the near future + */ + return (void *)(&layer); + } + /* no break here for other ob channel-types - as they can be done normally */ + + default: /* normal data-source */ + return get_ipo_poin(id, icu, vartype); + } + + /* not valid... */ + return NULL; +} + + +/* -------------- 'Smarter' Keyframing Functions -------------------- */ +/* return codes for new_key_needed */ +enum { + KEYNEEDED_DONTADD = 0, + KEYNEEDED_JUSTADD, + KEYNEEDED_DELPREV, + KEYNEEDED_DELNEXT +} eKeyNeededStatus; + +/* This helper function determines whether a new keyframe is needed */ +/* Cases where keyframes should not be added: + * 1. Keyframe to be added bewteen two keyframes with similar values + * 2. Keyframe to be added on frame where two keyframes are already situated + * 3. Keyframe lies at point that intersects the linear line between two keyframes + */ +static short new_key_needed (IpoCurve *icu, float cFrame, float nValue) +{ + BezTriple *bezt=NULL, *prev=NULL; + int totCount, i; + float valA = 0.0f, valB = 0.0f; + + /* safety checking */ + if (icu == NULL) return KEYNEEDED_JUSTADD; + totCount= icu->totvert; + if (totCount == 0) return KEYNEEDED_JUSTADD; + + /* loop through checking if any are the same */ + bezt= icu->bezt; + for (i=0; ivec[1][0]; + beztVal= bezt->vec[1][1]; + + if (prev) { + /* there is a keyframe before the one currently being examined */ + + /* get previous time+value */ + prevPosi= prev->vec[1][0]; + prevVal= prev->vec[1][1]; + + /* keyframe to be added at point where there are already two similar points? */ + if (IS_EQ(prevPosi, cFrame) && IS_EQ(beztPosi, cFrame) && IS_EQ(beztPosi, prevPosi)) { + return KEYNEEDED_DONTADD; + } + + /* keyframe between prev+current points ? */ + if ((prevPosi <= cFrame) && (cFrame <= beztPosi)) { + /* is the value of keyframe to be added the same as keyframes on either side ? */ + if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) { + return KEYNEEDED_DONTADD; + } + else { + float realVal; + + /* get real value of curve at that point */ + realVal= eval_icu(icu, cFrame); + + /* compare whether it's the same as proposed */ + if (IS_EQ(realVal, nValue)) + return KEYNEEDED_DONTADD; + else + return KEYNEEDED_JUSTADD; + } + } + + /* new keyframe before prev beztriple? */ + if (cFrame < prevPosi) { + /* A new keyframe will be added. However, whether the previous beztriple + * stays around or not depends on whether the values of previous/current + * beztriples and new keyframe are the same. + */ + if (IS_EQ(prevVal, nValue) && IS_EQ(beztVal, nValue) && IS_EQ(prevVal, beztVal)) + return KEYNEEDED_DELNEXT; + else + return KEYNEEDED_JUSTADD; + } + } + else { + /* just add a keyframe if there's only one keyframe + * and the new one occurs before the exisiting one does. + */ + if ((cFrame < beztPosi) && (totCount==1)) + return KEYNEEDED_JUSTADD; + } + + /* continue. frame to do not yet passed (or other conditions not met) */ + if (i < (totCount-1)) { + prev= bezt; + bezt++; + } + else + break; + } + + /* Frame in which to add a new-keyframe occurs after all other keys + * -> If there are at least two existing keyframes, then if the values of the + * last two keyframes and the new-keyframe match, the last existing keyframe + * gets deleted as it is no longer required. + * -> Otherwise, a keyframe is just added. 1.0 is added so that fake-2nd-to-last + * keyframe is not equal to last keyframe. + */ + bezt= (icu->bezt + (icu->totvert - 1)); + valA= bezt->vec[1][1]; + + if (prev) + valB= prev->vec[1][1]; + else + valB= bezt->vec[1][1] + 1.0f; + + if (IS_EQ(valA, nValue) && IS_EQ(valA, valB)) + return KEYNEEDED_DELPREV; + else + return KEYNEEDED_JUSTADD; +} + +/* ------------------ 'Visual' Keyframing Functions ------------------ */ + +/* internal status codes for visualkey_can_use */ +enum { + VISUALKEY_NONE = 0, + VISUALKEY_LOC, + VISUALKEY_ROT +}; + +/* This helper function determines if visual-keyframing should be used when + * inserting keyframes for the given channel. As visual-keyframing only works + * on Object and Pose-Channel blocks, this should only get called for those + * blocktypes, when using "standard" keying but 'Visual Keying' option in Auto-Keying + * settings is on. + */ +static short visualkey_can_use (ID *id, int blocktype, char *actname, char *constname, int adrcode) +{ + Object *ob= NULL; + bConstraint *con= NULL; + short searchtype= VISUALKEY_NONE; + + /* validate data */ + if ((id == NULL) || (GS(id->name)!=ID_OB) || !(ELEM(blocktype, ID_OB, ID_PO))) + return 0; + + /* get first constraint and determine type of keyframe constraints to check for*/ + ob= (Object *)id; + + if (blocktype == ID_OB) { + con= ob->constraints.first; + + if (ELEM3(adrcode, OB_LOC_X, OB_LOC_Y, OB_LOC_Z)) + searchtype= VISUALKEY_LOC; + else if (ELEM3(adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) + searchtype= VISUALKEY_ROT; + } + else if (blocktype == ID_PO) { + bPoseChannel *pchan= get_pose_channel(ob->pose, actname); + con= pchan->constraints.first; + + if (ELEM3(adrcode, AC_LOC_X, AC_LOC_Y, AC_LOC_Z)) + searchtype= VISUALKEY_LOC; + else if (ELEM4(adrcode, AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z)) + searchtype= VISUALKEY_ROT; + } + + /* only search if a searchtype and initial constraint are available */ + if (searchtype && con) { + for (; con; con= con->next) { + /* only consider constraint if it is not disabled, and has influence */ + if (con->flag & CONSTRAINT_DISABLE) continue; + if (con->enforce == 0.0f) continue; + + /* some constraints may alter these transforms */ + switch (con->type) { + /* multi-transform constraints */ + case CONSTRAINT_TYPE_CHILDOF: + return 1; + case CONSTRAINT_TYPE_TRANSFORM: + return 1; + case CONSTRAINT_TYPE_FOLLOWPATH: + return 1; + + /* single-transform constraits */ + case CONSTRAINT_TYPE_TRACKTO: + if (searchtype==VISUALKEY_ROT) return 1; + break; + case CONSTRAINT_TYPE_ROTLIMIT: + if (searchtype==VISUALKEY_ROT) return 1; + break; + case CONSTRAINT_TYPE_LOCLIMIT: + if (searchtype==VISUALKEY_LOC) return 1; + break; + case CONSTRAINT_TYPE_ROTLIKE: + if (searchtype==VISUALKEY_ROT) return 1; + break; + case CONSTRAINT_TYPE_LOCLIKE: + if (searchtype==VISUALKEY_LOC) return 1; + break; + case CONSTRAINT_TYPE_LOCKTRACK: + if (searchtype==VISUALKEY_ROT) return 1; + break; + case CONSTRAINT_TYPE_MINMAX: + if (searchtype==VISUALKEY_LOC) return 1; + break; + + default: + break; + } + } + } + + /* when some condition is met, this function returns, so here it can be 0 */ + return 0; +} + +/* This helper function extracts the value to use for visual-keyframing + * In the event that it is not possible to perform visual keying, try to fall-back + * to using the poin method. Assumes that all data it has been passed is valid. + */ +static float visualkey_get_value (ID *id, int blocktype, char *actname, char *constname, int adrcode, IpoCurve *icu) +{ + Object *ob; + void *poin = NULL; + int index, vartype; + + /* validate situtation */ + if ((id==NULL) || (GS(id->name)!=ID_OB) || (ELEM(blocktype, ID_OB, ID_PO)==0)) + return 0.0f; + + /* get object */ + ob= (Object *)id; + + /* only valid for objects or posechannels */ + if (blocktype == ID_OB) { + /* parented objects are not supported, as the effects of the parent + * are included in the matrix, which kindof beats the point + */ + if ((ob) && (ob->parent==NULL)) { + /* only Location or Rotation keyframes are supported now */ + if (ELEM3(adrcode, OB_LOC_X, OB_LOC_Y, OB_LOC_Z)) { + /* assumes that OB_LOC_Z > OB_LOC_Y > OB_LOC_X */ + index= adrcode - OB_LOC_X; + + return ob->obmat[3][index]; + } + else if (ELEM3(adrcode, OB_ROT_X, OB_ROT_Y, OB_ROT_Z)) { + float eul[3]; + + /* assumes that OB_ROT_Z > OB_ROT_Y > OB_ROT_X */ + index= adrcode - OB_ROT_X; + + Mat4ToEul(ob->obmat, eul); + return eul[index]*(5.72958); + } + } + } + else if (blocktype == ID_PO) { + bPoseChannel *pchan; + float tmat[4][4]; + + /* get data to use */ + pchan= get_pose_channel(ob->pose, actname); + + /* Although it is not strictly required for this particular space conversion, + * arg1 must not be null, as there is a null check for the other conversions to + * be safe. Therefore, the active object is passed here, and in many cases, this + * will be what owns the pose-channel that is getting this anyway. + */ + Mat4CpyMat4(tmat, pchan->pose_mat); + constraint_mat_convertspace(ob, pchan, tmat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL); + + /* Loc, Rot/Quat keyframes are supported... */ + if (ELEM3(adrcode, AC_LOC_X, AC_LOC_Y, AC_LOC_Z)) { + /* assumes that AC_LOC_Z > AC_LOC_Y > AC_LOC_X */ + index= adrcode - AC_LOC_X; + + /* only use for non-connected bones */ + if ((pchan->bone->parent) && !(pchan->bone->flag & BONE_CONNECTED)) + return tmat[3][index]; + else if (pchan->bone->parent == NULL) + return tmat[3][index]; + } + else if (ELEM4(adrcode, AC_QUAT_W, AC_QUAT_X, AC_QUAT_Y, AC_QUAT_Z)) { + float tmat[4][4], trimat[3][3], quat[4]; + + /* assumes that AC_QUAT_Z > AC_QUAT_Y > AC_QUAT_X > AC_QUAT_W */ + index= adrcode - AC_QUAT_W; + + Mat3CpyMat4(trimat, tmat); + Mat3ToQuat_is_ok(trimat, quat); + + return quat[index]; + } + } + + /* as the function hasn't returned yet, try reading from poin */ + get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); + if (poin) + return read_ipo_poin(poin, vartype); +} + + +/* ------------------------- Insert Key API ------------------------- */ + +/* Main Keyframing API call: + * Use this when validation of necessary animation data isn't necessary as it + * already exists. It will insert a keyframe using the current value being keyframed. + * + * The flag argument is used for special settings that alter the behaviour of + * the keyframe insertion. These include the 'visual' keyframing modes, quick refresh, + * and extra keyframe filtering. + */ +short insertkey (ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag) +{ + IpoCurve *icu; + + /* get ipo-curve */ + icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); + + /* only continue if we have an ipo-curve to add keyframe to */ + if (icu) { + float cfra = frame_to_float(CFRA); + float curval= 0.0f; + void *poin = NULL; + int vartype; + + /* apply special time tweaking */ + if (GS(id->name) == ID_OB) { + Object *ob= (Object *)id; + + /* apply NLA-scaling (if applicable) */ + if (actname && actname[0]) + cfra= get_action_frame(ob, cfra); + + /* ancient time-offset cruft */ + if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) { + /* actually frametofloat calc again! */ + cfra-= give_timeoffset(ob)*G.scene->r.framelen; + } + } + + /* get pointer to data to read from */ + poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); + if (poin == NULL) return 0; + + /* obtain value to give keyframe */ + if ( (flag & INSERTKEY_MATRIX) && + (visualkey_can_use(id, blocktype, actname, constname, adrcode)) ) + { + /* visual-keying is only available for object and pchan datablocks, as + * it works by keyframing using a value extracted from the final matrix + * instead of using the kt system to extract a value. + */ + curval= visualkey_get_value(id, blocktype, actname, constname, adrcode, icu); + } + else { + /* use kt's read_poin function to extract value (kt->read_poin should + * exist in all cases, but it never hurts to check) + */ + curval= read_ipo_poin(poin, vartype); + } + + /* only insert keyframes where they are needed */ + if (flag & INSERTKEY_NEEDED) { + short insert_mode; + + /* check whether this curve really needs a new keyframe */ + insert_mode= new_key_needed(icu, cfra, curval); + + /* insert new keyframe at current frame */ + if (insert_mode) + insert_vert_icu(icu, cfra, curval, (flag & INSERTKEY_FAST)); + + /* delete keyframe immediately before/after newly added */ + switch (insert_mode) { + case KEYNEEDED_DELPREV: + delete_icu_key(icu, icu->totvert-2, 1); + break; + case KEYNEEDED_DELNEXT: + delete_icu_key(icu, 1, 1); + break; + } + } + else { + /* just insert keyframe */ + insert_vert_icu(icu, cfra, curval, (flag & INSERTKEY_FAST)); + } + + /* return success */ + return 1; + } + + /* return failure */ + return 0; +} + + +/* ************************************************** */ +/* KEYFRAME DELETION */ + +/* Main Keyframing API call: + * Use this when validation of necessary animation data isn't necessary as it + * already exists. It will delete a keyframe at the current frame. + * + * The flag argument is used for special settings that alter the behaviour of + * the keyframe deletion. These include the quick refresh options. + */ +short deletekey (ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag) +{ + IpoCurve *icu; + + // locate ipo-curve + icu= NULL; // fixme.. + + // TODO: implement me! + + /* return failure */ + return 0; +} + +/* ************************************************** */ +/* COMMON KEYFRAME MANAGEMENT (common_insertkey/deletekey) */ + + +/* ------------- KeyingSet Defines ------------ */ +/* Note: these must all be named with the defks_* prefix, otherwise the template macro will not work! */ + +/* macro for defining keyingset contexts */ +#define KSC_TEMPLATE(ctx_name) {&defks_##ctx_name[0], NULL, sizeof(defks_##ctx_name)/sizeof(bKeyingSet)} + +/* --- */ + +/* Object KeyingSets ------ */ + +/* check if include shapekey entry */ +static short incl_v3d_ob_shapekey (bKeyingSet *ks, const char mode[]) +{ + Object *ob= (G.obedit)? (G.obedit) : (OBACT); + char *newname= NULL; + + /* not available for delete mode */ + if (strcmp(mode, "Delete")==0) + return 0; + + /* check if is geom object that can get shapekeys */ + switch (ob->type) { + /* geometry? */ + case OB_MESH: newname= "Mesh"; break; + case OB_CURVE: newname= "Curve"; break; + case OB_SURF: newname= "Surface"; break; + case OB_LATTICE: newname= "Lattice"; break; + + /* not geometry! */ + default: + return 0; + } + + /* if ks is shapekey entry (this could be callled for separator before too!) */ + if (ks->flag == -3) + sprintf(ks->name, newname); + + /* if it gets here, it's ok */ + return 1; +} + +/* array for object keyingset defines */ +bKeyingSet defks_v3d_object[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "Loc", ID_OB, 0, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}}, + {NULL, "Rot", ID_OB, 0, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, + {NULL, "Scale", ID_OB, 0, 3, {OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "LocRot", ID_OB, 0, 6, + {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, + OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, + + {NULL, "LocScale", ID_OB, 0, 6, + {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, + OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, + + {NULL, "LocRotScale", ID_OB, 0, 9, + {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, + OB_ROT_X,OB_ROT_Y,OB_ROT_Z, + OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, + + {NULL, "RotScale", ID_OB, 0, 6, + {OB_ROT_X,OB_ROT_Y,OB_ROT_Z, + OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "VisualLoc", ID_OB, INSERTKEY_MATRIX, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}}, + {NULL, "VisualRot", ID_OB, INSERTKEY_MATRIX, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, + + {NULL, "VisualLocRot", ID_OB, INSERTKEY_MATRIX, 6, + {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, + OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "Layer", ID_OB, 0, 1, {OB_LAY}}, // icky option... + {NULL, "Available", ID_OB, -2, 0, {}}, + + {incl_v3d_ob_shapekey, "%l%l", 0, -1, 0, {}}, // separator (linked to shapekey entry) + {incl_v3d_ob_shapekey, "", ID_OB, -3, 0, {}} +}; + +/* PoseChannel KeyingSets ------ */ + +/* array for posechannel keyingset defines */ +bKeyingSet defks_v3d_pchan[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "Loc", ID_PO, 0, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}}, + {NULL, "Rot", ID_PO, 0, 4, {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, + {NULL, "Scale", ID_PO, 0, 3, {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "LocRot", ID_PO, 0, 7, + {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W, + AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, + + {NULL, "LocScale", ID_PO, 0, 6, + {AC_LOC_X,AC_LOC_Y,AC_LOC_Z, + AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, + + {NULL, "LocRotScale", ID_PO, 0, 10, + {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W,AC_QUAT_X, + AC_QUAT_Y,AC_QUAT_Z,AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, + + {NULL, "RotScale", ID_PO, 0, 7, + {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z, + AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "VisualLoc", ID_PO, INSERTKEY_MATRIX, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}}, + {NULL, "VisualRot", ID_PO, INSERTKEY_MATRIX, 3, {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, + + {NULL, "VisualLocRot", ID_PO, INSERTKEY_MATRIX, 7, + {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W, + AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "Available", ID_PO, -2, 0, {}} +}; + +/* Material KeyingSets ------ */ + +/* array for material keyingset defines */ +bKeyingSet defks_buts_shading_mat[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "RGB", ID_MA, 0, 3, {MA_COL_R,MA_COL_G,MA_COL_B}}, + {NULL, "Alpha", ID_MA, 0, 1, {MA_ALPHA}}, + {NULL, "Halo Size", ID_MA, 0, 1, {MA_HASIZE}}, + {NULL, "Mode", ID_MA, 0, 1, {MA_MODE}}, // evil bitflags + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "All Color", ID_MA, 0, 18, + {MA_COL_R,MA_COL_G,MA_COL_B, + MA_ALPHA,MA_HASIZE, MA_MODE, + MA_SPEC_R,MA_SPEC_G,MA_SPEC_B, + MA_REF,MA_EMIT,MA_AMB,MA_SPEC,MA_HARD, + MA_MODE,MA_TRANSLU,MA_ADD}}, + + {NULL, "All Mirror", ID_MA, 0, 5, + {MA_RAYM,MA_FRESMIR,MA_FRESMIRI, + MA_FRESTRA,MA_FRESTRAI}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "Ofs", ID_MA, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}}, + {NULL, "Size", ID_MA, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}}, + + {NULL, "All Mapping", ID_MA, 0, 14, + {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z, + MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z, + MAP_R,MAP_G,MAP_B,MAP_DVAR, + MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "Available", ID_MA, -2, 0, {}} +}; + +/* World KeyingSets ------ */ + +/* array for world keyingset defines */ +bKeyingSet defks_buts_shading_wo[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "Zenith RGB", ID_WO, 0, 3, {WO_ZEN_R,WO_ZEN_G,WO_ZEN_B}}, + {NULL, "Horizon RGB", ID_WO, 0, 3, {WO_HOR_R,WO_HOR_G,WO_HOR_B}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "Mist", ID_WO, 0, 4, {WO_MISI,WO_MISTDI,WO_MISTSTA,WO_MISTHI}}, + {NULL, "Stars", ID_WO, 0, 5, {WO_STAR_R,WO_STAR_G,WO_STAR_B,WO_STARDIST,WO_STARSIZE}}, + + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "Ofs", ID_WO, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}}, + {NULL, "Size", ID_WO, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}}, + + {NULL, "All Mapping", ID_WO, 0, 14, + {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z, + MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z, + MAP_R,MAP_G,MAP_B,MAP_DVAR, + MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "Available", ID_WO, -2, 0, {}} +}; + +/* Lamp KeyingSets ------ */ + +/* array for lamp keyingset defines */ +bKeyingSet defks_buts_shading_la[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "RGB", ID_LA, 0, 3, {LA_COL_R,LA_COL_G,LA_COL_B}}, + {NULL, "Energy", ID_LA, 0, 1, {LA_ENERGY}}, + {NULL, "Spot Size", ID_LA, 0, 1, {LA_SPOTSI}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "Ofs", ID_LA, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}}, + {NULL, "Size", ID_LA, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}}, + + {NULL, "All Mapping", ID_LA, 0, 14, + {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z, + MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z, + MAP_R,MAP_G,MAP_B,MAP_DVAR, + MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "Available", ID_LA, -2, 0, {}} +}; + +/* Texture KeyingSets ------ */ + +/* array for texture keyingset defines */ +bKeyingSet defks_buts_shading_tex[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "Clouds", ID_TE, 0, 5, + {TE_NSIZE,TE_NDEPTH,TE_NTYPE, + TE_MG_TYP,TE_N_BAS1}}, + + {NULL, "Marble", ID_TE, 0, 7, + {TE_NSIZE,TE_NDEPTH,TE_NTYPE, + TE_TURB,TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}}, + + {NULL, "Stucci", ID_TE, 0, 5, + {TE_NSIZE,TE_NTYPE,TE_TURB, + TE_MG_TYP,TE_N_BAS1}}, + + {NULL, "Wood", ID_TE, 0, 6, + {TE_NSIZE,TE_NTYPE,TE_TURB, + TE_MG_TYP,TE_N_BAS1,TE_N_BAS2}}, + + {NULL, "Magic", ID_TE, 0, 2, {TE_NDEPTH,TE_TURB}}, + + {NULL, "Blend", ID_TE, 0, 1, {TE_MG_TYP}}, + + {NULL, "Musgrave", ID_TE, 0, 6, + {TE_MG_TYP,TE_MGH,TE_MG_LAC, + TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN}}, + + {NULL, "Voronoi", ID_TE, 0, 9, + {TE_VNW1,TE_VNW2,TE_VNW3,TE_VNW4, + TE_VNMEXP,TE_VN_DISTM,TE_VN_COLT, + TE_ISCA,TE_NSIZE}}, + + {NULL, "Distorted Noise", ID_TE, 0, 4, + {TE_MG_OCT,TE_MG_OFF,TE_MG_GAIN,TE_DISTA}}, + + {NULL, "Color Filter", ID_TE, 0, 5, + {TE_COL_R,TE_COL_G,TE_COL_B,TE_BRIGHT,TE_CONTRA}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "Available", ID_TE, -2, 0, {}} +}; + +/* Object Buttons KeyingSets ------ */ + +/* check if include particles entry */ +static short incl_buts_ob (bKeyingSet *ks, const char mode[]) +{ + Object *ob= OBACT; + /* only if object is mesh type */ + return (ob->type == OB_MESH); +} + +/* array for texture keyingset defines */ +bKeyingSet defks_buts_object[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {incl_buts_ob, "Surface Damping", ID_OB, 0, 1, {OB_PD_SDAMP}}, + {incl_buts_ob, "Random Damping", ID_OB, 0, 1, {OB_PD_RDAMP}}, + {incl_buts_ob, "Permeability", ID_OB, 0, 1, {OB_PD_PERM}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "Force Strength", ID_OB, 0, 1, {OB_PD_FSTR}}, + {NULL, "Force Falloff", ID_OB, 0, 1, {OB_PD_FFALL}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "Available", ID_OB, -2, 0, {}} // this will include ob-transforms too! +}; + +/* Camera Buttons KeyingSets ------ */ + +/* check if include internal-renderer entry */ +static short incl_buts_cam1 (bKeyingSet *ks, const char mode[]) +{ + /* only if renderer is internal renderer */ + return (G.scene->r.renderer==R_INTERN); +} + +/* check if include external-renderer entry */ +static short incl_buts_cam2 (bKeyingSet *ks, const char mode[]) +{ + /* only if renderer is internal renderer */ + return (G.scene->r.renderer!=R_INTERN); +} + +/* array for camera keyingset defines */ +bKeyingSet defks_buts_cam[] = +{ + /* include_cb, name, blocktype, flag, chan_num, adrcodes */ + {NULL, "Lens", ID_CA, 0, 1, {CAM_LENS}}, + {NULL, "Clipping", ID_CA, 0, 2, {CAM_STA,CAM_END}}, + {NULL, "Focal Distance", ID_CA, 0, 1, {CAM_YF_FDIST}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + + {incl_buts_cam2, "Aperture", ID_CA, 0, 1, {CAM_YF_APERT}}, + {incl_buts_cam1, "Viewplane Shift", ID_CA, 0, 2, {CAM_SHIFT_X,CAM_SHIFT_Y}}, + + {NULL, "%l", 0, -1, 0, {}}, // separator + + {NULL, "Available", ID_CA, -2, 0, {}} +}; + +/* --- */ + +/* Keying Context Defines - Must keep in sync with enumeration (eKS_Contexts) */ +bKeyingContext ks_contexts[] = +{ + KSC_TEMPLATE(v3d_object), + KSC_TEMPLATE(v3d_pchan), + + KSC_TEMPLATE(buts_shading_mat), + KSC_TEMPLATE(buts_shading_wo), + KSC_TEMPLATE(buts_shading_la), + KSC_TEMPLATE(buts_shading_tex), + + KSC_TEMPLATE(buts_object), + KSC_TEMPLATE(buts_cam) +}; + +/* Keying Context Enumeration - Must keep in sync with definitions*/ +typedef enum eKS_Contexts { + KSC_V3D_OBJECT = 0, + KSC_V3D_PCHAN, + + KSC_BUTS_MAT, + KSC_BUTS_WO, + KSC_BUTS_LA, + KSC_BUTS_TEX, + + KSC_BUTS_OB, + KSC_BUTS_CAM, + + /* make sure this last one remains untouched! */ + KSC_TOT_TYPES +} eKS_Contexts; + + +/* ---------------- KeyingSet Tools ------------------- */ + +/* helper for commonkey_context_get() - get keyingsets for 3d-view */ +static void commonkey_context_getv3d (ListBase *sources, bKeyingContext **ksc) +{ + Object *ob; + IpoCurve *icu; + + if ((OBACT) && (OBACT->flag & OB_POSEMODE)) { + bPoseChannel *pchan; + + /* pose-level */ + ob= OBACT; + *ksc= &ks_contexts[KSC_V3D_PCHAN]; + set_pose_keys(ob); /* sets pchan->flag to POSE_KEY if bone selected, and clears if not */ + + /* loop through posechannels */ + for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) { + if (pchan->flag & POSE_KEY) { + bCommonKeySrc *cks; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set id-block to key to, and action */ + cks->id= (ID *)ob; + cks->act= ob->action; + + /* set pchan */ + cks->pchan= pchan; + cks->actname= pchan->name; + } + } + } + else { + Base *base; + + /* object-level */ + *ksc= &ks_contexts[KSC_V3D_OBJECT]; + + /* loop through bases */ + for (base= FIRSTBASE; base; base= base->next) { + if (TESTBASELIB(base)) { + bCommonKeySrc *cks; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set id-block to key to */ + ob= base->object; + cks->id= (ID *)ob; + + /* when ob's keyframes are in an action, default to using 'Object' as achan name */ + if (ob->ipoflag & OB_ACTION_OB) + cks->actname= "Object"; + + /* set ipo-flags */ + // TODO: add checks for lib-linked data + if ((ob->ipo) || (ob->action)) { + if (ob->ipo) { + cks->ipo= ob->ipo; + } + else { + bActionChannel *achan; + + cks->act= ob->action; + achan= get_action_channel(ob->action, cks->actname); + + if (achan && achan->ipo) + cks->ipo= achan->ipo; + } + + /* deselect all ipo-curves */ + for (icu= cks->ipo->curve.first; icu; icu= icu->next) { + icu->flag &= ~IPO_SELECT; + } + } + } + } + } +} + +/* helper for commonkey_context_get() - get keyingsets for buttons window */ +// nb - for mtex entries... need to set map (= texchan_to_adrcode(id->texact) +static void commonkey_context_getsbuts (ListBase *sources, bKeyingContext **ksc) +{ + bCommonKeySrc *cks; + + /* check on tab-type */ + switch (G.buts->mainb) { + case CONTEXT_SHADING: /* ------------- Shading buttons ---------------- */ + /* subtabs include "Material", "Texture", "Lamp", "World"*/ + switch (G.buts->tab[CONTEXT_SHADING]) { + case TAB_SHADING_MAT: /* >------------- Material Tab -------------< */ + { + Material *ma= editnode_get_active_material(G.buts->lockpoin); + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set data */ + cks->id= (ID *)ma; + cks->map= texchannel_to_adrcode(ma->texact); + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_MAT]; + return; + } + break; + case TAB_SHADING_WORLD: /* >------------- World Tab -------------< */ + { + World *wo= G.buts->lockpoin; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set data */ + cks->id= (ID *)wo; + cks->map= texchannel_to_adrcode(wo->texact); + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_WO]; + return; + } + break; + case TAB_SHADING_LAMP: /* >------------- Lamp Tab -------------< */ + { + Lamp *la= G.buts->lockpoin; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set data */ + cks->id= (ID *)la; + cks->map= texchannel_to_adrcode(la->texact); + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_LA]; + return; + } + break; + case TAB_SHADING_TEX: /* >------------- Texture Tab -------------< */ + { + Tex *te= G.buts->lockpoin; + + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set data */ + cks->id= (ID *)te; + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_TEX]; + return; + } + break; + } + break; + + case CONTEXT_OBJECT: /* ------------- Object buttons ---------------- */ + { + Object *ob= OBACT; + + if (ob) { + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set id-block to key to */ + cks->id= (ID *)ob; + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_OB]; + return; + } + } + break; + + case CONTEXT_EDITING: /* ------------- Editing buttons ---------------- */ + { + Object *ob= OBACT; + + if ((ob) && (ob->type==OB_CAMERA)) { /* >---------------- camera buttons ---------------< */ + /* add new keyframing destination */ + cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); + BLI_addtail(sources, cks); + + /* set id-block to key to */ + cks->id= (ID *)ob; + + /* set keyingsets */ + *ksc= &ks_contexts[KSC_BUTS_CAM]; + return; + } + } + break; + } + + /* if nothing happened... */ + *ksc= NULL; +} + + +/* get keyingsets for appropriate context */ +static void commonkey_context_get (ListBase *sources, bKeyingContext **ksc) +{ + /* check view type */ + switch (curarea->spacetype) { + /* 3d view - first one tested as most often used */ + case SPACE_VIEW3D: + commonkey_context_getv3d(sources, ksc); + break; + + /* buttons view */ + case SPACE_BUTS: + commonkey_context_getsbuts(sources, ksc); + break; + } +} + +/* flush updates after all operations */ +static void commonkey_context_finish (ListBase *sources) +{ + /* check view type */ + switch (curarea->spacetype) { + /* 3d view - first one tested as most often used */ + case SPACE_VIEW3D: + { + /* either pose or object level */ + if (OBACT && (OBACT->pose)) { + Object *ob= OBACT; + + /* recalculate ipo handles, etc. */ + if (ob->action) + remake_action_ipos(ob->action); + + /* recalculate bone-paths on adding new keyframe? */ + // TODO: currently, there is no setting to turn this on/off globally + if (ob->pose->flag & POSE_RECALCPATHS) + pose_recalculate_paths(ob); + } + else { + bCommonKeySrc *cks; + + /* loop over bases (as seen in sources) */ + for (cks= sources->first; cks; cks= cks->next) { + Object *ob= (Object *)cks->id; + + /* simply set recalc flag */ + ob->recalc |= OB_RECALC_OB; + } + } + } + break; + } +} + +/* flush refreshes after undo */ +static void commonkey_context_refresh (void) +{ + /* check view type */ + switch (curarea->spacetype) { + /* 3d view - first one tested as most often used */ + case SPACE_VIEW3D: + { + /* do refreshes */ + DAG_scene_flush_update(G.scene, screen_view3d_layers(), 0); + + allspace(REMAKEIPO, 0); + allqueue(REDRAWVIEW3D, 0); + allqueue(REDRAWMARKER, 0); + } + break; + } +} + +/* --- */ + +/* Build menu-string of available keying-sets (allocates memory for string) + * NOTE: mode must not be longer than 64 chars + */ +static char *build_keyingsets_menu (bKeyingContext *ksc, const char mode[48]) +{ + DynStr *pupds= BLI_dynstr_new(); + bKeyingSet *ks; + char buf[64]; + char *str; + int i, n; + + /* add title first */ + BLI_snprintf(buf, 64, "%s Key %%t|", mode); + BLI_dynstr_append(pupds, buf); + + /* loop through keyingsets, adding them */ + for (ks=ksc->keyingsets, i=0, n=1; i < ksc->tot; ks++, i++, n++) { + /* check if keyingset can be used */ + if (ks->flag == -1) { + /* optional separator? */ + if (ks->include_cb) { + if (ks->include_cb(ks, mode)) { + BLI_snprintf( buf, 64, "%s%s", ks->name, ((n < ksc->tot)?"|":"") ); + BLI_dynstr_append(pupds, buf); + } + } + else { + BLI_snprintf( buf, 64, "%%l%s", ((n < ksc->tot)?"|":"") ); + BLI_dynstr_append(pupds, buf); + } + } + else if ( (ks->include_cb==NULL) || (ks->include_cb(ks, mode)) ) { + /* entry can be included */ + BLI_dynstr_append(pupds, ks->name); + + /* check if special "shapekey" entry */ + if (ks->flag == -3) + BLI_snprintf( buf, 64, "%%x0%s", ((n < ksc->tot)?"|":"") ); + else + BLI_snprintf( buf, 64, "%%x%d%s", n, ((n < ksc->tot)?"|":"") ); + BLI_dynstr_append(pupds, buf); + } + } + + /* convert to normal MEM_malloc'd string */ + str= BLI_dynstr_get_cstring(pupds); + BLI_dynstr_free(pupds); + + return str; +} + +/* Get the keying set that was chosen by the user from the menu */ +static bKeyingSet *get_keyingset_fromcontext (bKeyingContext *ksc, short index) +{ + /* check if index is valid */ + if (ELEM(NULL, ksc, ksc->keyingsets)) + return NULL; + if ((index < 1) || (index > ksc->tot)) + return NULL; + + /* index starts from 1, and should directly correspond to keyingset in array */ + return (bKeyingSet *)(ksc->keyingsets + (index - 1)); +} + +/* ---------------- Keyframe Management API -------------------- */ + +/* mode for common_modifykey */ +enum { + COMMONKEY_MODE_INSERT = 0, + COMMONKEY_MODE_DELETE, +} eCommonModifyKey_Modes; + +/* Display a menu for handling the insertion of keyframes based on the active view */ +// TODO: add back an option for repeating last keytype +void common_modifykey (short mode) +{ + ListBase dsources = {NULL, NULL}; + bKeyingContext *ksc= NULL; + bCommonKeySrc *cks; + bKeyingSet *ks = NULL; + char *menustr, buf[64]; + short menu_nr; + + /* check if mode is valid */ + if (ELEM(mode, COMMONKEY_MODE_INSERT, COMMONKEY_MODE_DELETE)==0) + return; + + /* delegate to other functions or get keyingsets to use */ + switch (curarea->spacetype) { + /* spaces with their own methods */ + case SPACE_IPO: + if (mode == COMMONKEY_MODE_INSERT) + insertkey_editipo(); + return; + case SPACE_ACTION: + if (mode == COMMONKEY_MODE_INSERT) + insertkey_action(); + return; + + /* TODO: based on UI elements? will that even be handled here??? */ + + /* default - check per view */ + default: + /* get the keyingsets and the data to add keyframes to */ + commonkey_context_get(&dsources, &ksc); + break; + } + + /* check that there is data to operate on */ + if (ELEM(NULL, dsources.first, ksc)) { + BLI_freelistN(&dsources); + return; + } + + /* get menu and process it */ + if (mode == COMMONKEY_MODE_DELETE) + menustr= build_keyingsets_menu(ksc, "Delete"); + else + menustr= build_keyingsets_menu(ksc, "Insert"); + menu_nr= pupmenu(menustr); + if (menustr) MEM_freeN(menustr); + + /* no item selected or shapekey entry? */ + if (menu_nr < 1) { + /* free temp sources */ + BLI_freelistN(&dsources); + + /* check if insert new shapekey */ + if ((menu_nr == 0) && (mode == COMMONKEY_MODE_INSERT)) + insert_shapekey(OBACT); + else + ksc->lastused= NULL; + + return; + } + else { + /* try to get keyingset */ + ks= get_keyingset_fromcontext(ksc, menu_nr); + + if (ks == NULL) { + BLI_freelistN(&dsources); + return; + } + } + + /* loop over each destination, applying the keying set */ + for (cks= dsources.first; cks; cks= cks->next) { + short success= 0; + + /* special hacks for 'available' option */ + if (ks->flag == -2) { + IpoCurve *icu= NULL; + + /* get first IPO-curve */ + if (cks->act && cks->actname) { + bActionChannel *achan= get_action_channel(cks->act, cks->actname); + + // FIXME: what about constraint channels? + if (achan && achan->ipo) + icu= achan->ipo->curve.first; + } + else + icu= cks->ipo->curve.first; + + /* we get adrcodes directly from IPO curves (see method below...) */ + for (; icu; icu= icu->next) { + short flag; + + /* insert mode or delete mode */ + if (mode == COMMONKEY_MODE_DELETE) { + /* local flags only add on to global flags */ + flag = 0; + + /* delete keyframe */ + success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag); + } + else { + /* local flags only add on to global flags */ + flag = ks->flag; + if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX; + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED; + // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE; + + /* insert keyframe */ + success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, icu->adrcode, flag); + } + } + } + else { + int i; + + /* loop over channels available in keyingset */ + for (i=0; i < ks->chan_num; i++) { + short flag, adrcode; + + /* get adrcode + * - certain adrcodes (for MTEX channels need special offsets) // BAD CRUFT!!! + */ + adrcode= ks->adrcodes[i]; + if (ELEM3(ks->blocktype, ID_MA, ID_LA, ID_WO)) { + switch (adrcode) { + case MAP_OFS_X: case MAP_OFS_Y: case MAP_OFS_Z: + case MAP_SIZE_X: case MAP_SIZE_Y: case MAP_SIZE_Z: + case MAP_R: case MAP_G: case MAP_B: case MAP_DVAR: + case MAP_COLF: case MAP_NORF: case MAP_VARF: case MAP_DISP: + adrcode += cks->map; + break; + } + } + + /* insert mode or delete mode */ + if (mode == COMMONKEY_MODE_DELETE) { + /* local flags only add on to global flags */ + flag = 0; + + /* delete keyframe */ + success += deletekey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag); + } + else { + /* local flags only add on to global flags */ + flag = ks->flag; + if (IS_AUTOKEY_FLAG(AUTOMATKEY)) flag |= INSERTKEY_MATRIX; + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) flag |= INSERTKEY_NEEDED; + // if (IS_AUTOKEY_MODE(EDITKEYS)) flag |= INSERTKEY_REPLACE; + + /* insert keyframe */ + success += insertkey(cks->id, ks->blocktype, cks->actname, cks->constname, adrcode, flag); + } + } + } + + /* special handling for some key-sources */ + if (success) { + /* set pose recalc-paths flag */ + if (cks->pchan) { + Object *ob= (Object *)cks->id; + bPoseChannel *pchan= cks->pchan; + + /* set flag to trigger path recalc */ + if (pchan->path) + ob->pose->flag |= POSE_RECALCPATHS; + + /* clear unkeyed flag (it doesn't matter if it's set or not) */ + if (pchan->bone) + pchan->bone->flag &= ~BONE_UNKEYED; + } + } + } + + /* apply post-keying flushes for this data sources */ + commonkey_context_finish(&dsources); + ksc->lastused= ks; + + /* free temp data */ + BLI_freelistN(&dsources); + + /* undo pushes */ + if (mode == COMMONKEY_MODE_DELETE) + BLI_snprintf(buf, 64, "Delete %s Key", ks->name); + else + BLI_snprintf(buf, 64, "Insert %s Key", ks->name); + BIF_undo_push(buf); + + /* queue updates for contexts */ + commonkey_context_refresh(); +} + +/* ---- */ + +/* used to insert keyframes from any view */ +void common_insertkey (void) +{ + common_modifykey(COMMONKEY_MODE_INSERT); +} + +/* used to insert keyframes from any view */ +void common_deletekey (void) +{ + common_modifykey(COMMONKEY_MODE_DELETE); +} + +/* ************************************************** */ diff --git a/source/blender/src/poselib.c b/source/blender/src/poselib.c index 6aeef7c75c2..ff54ad31e22 100644 --- a/source/blender/src/poselib.c +++ b/source/blender/src/poselib.c @@ -61,7 +61,7 @@ #include "BKE_global.h" #include "BKE_utildefines.h" -//#include "BIF_keyframing.h" +#include "BIF_keyframing.h" #include "BSE_editipo.h" #include "BDR_drawaction.h" diff --git a/source/blender/src/poseobject.c b/source/blender/src/poseobject.c index 28b8729a247..19fb8dc2ecd 100644 --- a/source/blender/src/poseobject.c +++ b/source/blender/src/poseobject.c @@ -69,6 +69,7 @@ #include "BIF_gl.h" #include "BIF_graphics.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_poseobject.h" #include "BIF_space.h" #include "BIF_toolbox.h" @@ -406,6 +407,7 @@ void pose_recalculate_paths(Object *ob) waitcursor(0); CFRA= cfra; + ob->pose->flag &= ~POSE_RECALCPATHS; allqueue(REDRAWVIEW3D, 0); /* recalc tags are still there */ allqueue(REDRAWBUTSEDIT, 0); } diff --git a/source/blender/src/toets.c b/source/blender/src/toets.c index efd97ed9786..8bd10b7186d 100644 --- a/source/blender/src/toets.c +++ b/source/blender/src/toets.c @@ -75,6 +75,7 @@ #include "BIF_imasel.h" #include "BIF_editparticle.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_poseobject.h" #include "BIF_previewrender.h" #include "BIF_renderwin.h" diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index 5b2120424f1..f38affde418 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -93,6 +93,7 @@ #include "BIF_graphics.h" #include "BIF_imasel.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_mainqueue.h" #include "BIF_mywindow.h" #include "BIF_renderwin.h" diff --git a/source/blender/src/transform_conversions.c b/source/blender/src/transform_conversions.c index 0984b2c3175..210a81927c8 100644 --- a/source/blender/src/transform_conversions.c +++ b/source/blender/src/transform_conversions.c @@ -108,6 +108,7 @@ #include "BIF_editsima.h" #include "BIF_editparticle.h" #include "BIF_gl.h" +#include "BIF_keyframing.h" #include "BIF_poseobject.h" #include "BIF_meshtools.h" #include "BIF_mywindow.h" @@ -3562,22 +3563,25 @@ short autokeyframe_cfra_can_key(Object *ob) */ void autokeyframe_ob_cb_func(Object *ob, int tmode) { + ID *id= (ID *)(ob); IpoCurve *icu; if (autokeyframe_cfra_can_key(ob)) { char *actname = NULL; + short flag = 0; if (ob->ipoflag & OB_ACTION_OB) actname= "Object"; + + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) + flag |= INSERTKEY_NEEDED; + if (IS_AUTOKEY_FLAG(AUTOMATKEY)) + flag |= INSERTKEY_MATRIX; if (IS_AUTOKEY_FLAG(INSERTAVAIL)) { + /* only key on available channels */ if ((ob->ipo) || (ob->action)) { - ID *id= (ID *)(ob); - - if (ob->ipo) { - icu= ob->ipo->curve.first; - } - else { + if (ob->action && actname) { bActionChannel *achan; achan= get_action_channel(ob->action, actname); @@ -3586,19 +3590,16 @@ void autokeyframe_ob_cb_func(Object *ob, int tmode) else icu= NULL; } + else + icu= ob->ipo->curve.first; - while (icu) { + for (; icu; icu= icu->next) { icu->flag &= ~IPO_SELECT; - if (IS_AUTOKEY_FLAG(INSERTNEEDED)) - insertkey_smarter(id, ID_OB, actname, NULL, icu->adrcode); - else - insertkey(id, ID_OB, actname, NULL, icu->adrcode, 0); - icu= icu->next; + insertkey(id, ID_OB, actname, NULL, icu->adrcode, flag); } } } else if (IS_AUTOKEY_FLAG(INSERTNEEDED)) { - ID *id= (ID *)(ob); short doLoc=0, doRot=0, doScale=0; /* filter the conditions when this happens (assume that curarea->spacetype==SPACE_VIE3D) */ @@ -3629,35 +3630,33 @@ void autokeyframe_ob_cb_func(Object *ob, int tmode) } if (doLoc) { - insertkey_smarter(id, ID_OB, actname, NULL, OB_LOC_X); - insertkey_smarter(id, ID_OB, actname, NULL, OB_LOC_Y); - insertkey_smarter(id, ID_OB, actname, NULL, OB_LOC_Z); + insertkey(id, ID_OB, actname, NULL, OB_LOC_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_LOC_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_LOC_Z, flag); } if (doRot) { - insertkey_smarter(id, ID_OB, actname, NULL, OB_ROT_X); - insertkey_smarter(id, ID_OB, actname, NULL, OB_ROT_Y); - insertkey_smarter(id, ID_OB, actname, NULL, OB_ROT_Z); + insertkey(id, ID_OB, actname, NULL, OB_ROT_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_ROT_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_ROT_Z, flag); } if (doScale) { - insertkey_smarter(id, ID_OB, actname, NULL, OB_SIZE_X); - insertkey_smarter(id, ID_OB, actname, NULL, OB_SIZE_Y); - insertkey_smarter(id, ID_OB, actname, NULL, OB_SIZE_Z); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z, flag); } } else { - ID *id= (ID *)(ob); + insertkey(id, ID_OB, actname, NULL, OB_LOC_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_LOC_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_LOC_Z, flag); - insertkey(id, ID_OB, actname, NULL, OB_LOC_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_LOC_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_LOC_Z, 0); + insertkey(id, ID_OB, actname, NULL, OB_ROT_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_ROT_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_ROT_Z, flag); - insertkey(id, ID_OB, actname, NULL, OB_ROT_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_ROT_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_ROT_Z, 0); - - insertkey(id, ID_OB, actname, NULL, OB_SIZE_X, 0); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y, 0); - insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z, 0); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_X, flag); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_Y, flag); + insertkey(id, ID_OB, actname, NULL, OB_SIZE_Z, flag); } remake_object_ipos(ob); @@ -3683,8 +3682,15 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) act= ob->action; if (autokeyframe_cfra_can_key(ob)) { + short flag= 0; + if (act == NULL) act= ob->action= add_empty_action("Action"); + + if (IS_AUTOKEY_FLAG(INSERTNEEDED)) + flag |= INSERTKEY_NEEDED; + if (IS_AUTOKEY_FLAG(AUTOMATKEY)) + flag |= INSERTKEY_MATRIX; for (pchan=pose->chanbase.first; pchan; pchan=pchan->next) { if (pchan->bone->flag & BONE_TRANSFORM) { @@ -3695,17 +3701,10 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) if (IS_AUTOKEY_FLAG(INSERTAVAIL)) { bActionChannel *achan; - for (achan = act->chanbase.first; achan; achan=achan->next) { - if ((achan->ipo) && !strcmp(achan->name, pchan->name)) { - for (icu = achan->ipo->curve.first; icu; icu=icu->next) { - /* only insert keyframe if needed? */ - if (IS_AUTOKEY_FLAG(INSERTNEEDED)) - insertkey_smarter(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode); - else - insertkey(&ob->id, ID_PO, pchan->name, NULL, icu->adrcode, 0); - } - break; - } + achan= get_action_channel(act, pchan->name); + if (achan && achan->ipo) { + for (icu= achan->ipo->curve.first; icu; icu= icu->next) + insertkey(id, ID_PO, pchan->name, NULL, icu->adrcode, flag); } } /* only insert keyframe if needed? */ @@ -3735,65 +3734,36 @@ void autokeyframe_pose_cb_func(Object *ob, int tmode, short targetless_ik) } if (doLoc) { - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_LOC_X); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_LOC_Y); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_LOC_Z); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, flag); } if (doRot) { - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_QUAT_W); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_QUAT_X); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_QUAT_Y); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_QUAT_Z); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, flag); } if (doScale) { - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_SIZE_X); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_SIZE_Y); - insertkey_smarter(id, ID_PO, pchan->name, NULL, AC_SIZE_Z); - } - } - else if (IS_AUTOKEY_FLAG(AUTOMATKEY)) { - int matok=0; - - /* check one to make sure we're not trying to set visual loc keys on - bones inside of a chain, which only leads to tears. */ - matok= insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_X); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z); - - if (matok == 0) { - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); - } - - /* check one to make sure we're not trying to set visual rot keys on - bones inside of a chain, which only leads to tears. */ - matok= insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y); - insertmatrixkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z); - - if (matok == 0) { - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, flag); } } /* insert keyframe in any channel that's appropriate */ else { - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_SIZE_Z, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_W, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_QUAT_Z, flag); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, 0); - insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, 0); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_X, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Y, flag); + insertkey(id, ID_PO, pchan->name, NULL, AC_LOC_Z, flag); } } } From 1a917f50a625f5c04a54157ec6bc6e786afce774 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 14 Sep 2008 05:10:45 +0000 Subject: [PATCH 057/125] running scripts in background mode would crash in some cases. (tested all scripts, none segfault now) --- source/blender/python/api2_2x/BGL.h | 9 +- source/blender/python/api2_2x/Draw.c | 110 ++++++++++++++++++++++- source/blender/python/api2_2x/Window.c | 13 ++- source/blender/python/api2_2x/bpy_data.c | 16 +++- 4 files changed, 134 insertions(+), 14 deletions(-) diff --git a/source/blender/python/api2_2x/BGL.h b/source/blender/python/api2_2x/BGL.h index ce972795322..461f5bc9372 100644 --- a/source/blender/python/api2_2x/BGL.h +++ b/source/blender/python/api2_2x/BGL.h @@ -323,8 +323,13 @@ typedef struct _Buffer { #define ret_def_GLstring const unsigned char *ret_str; #define ret_set_GLstring ret_str= -#define ret_ret_GLstring return PyString_FromString(ret_str); - +#define ret_ret_GLstring \ + if (ret_str) {\ + return PyString_FromString(ret_str);\ + } else {\ + PyErr_SetString(PyExc_AttributeError, "could not get opengl string");\ + return NULL;\ + } #endif /* EXPP_BGL_H */ diff --git a/source/blender/python/api2_2x/Draw.c b/source/blender/python/api2_2x/Draw.c index bd19a6a6a3e..b04366d5579 100644 --- a/source/blender/python/api2_2x/Draw.c +++ b/source/blender/python/api2_2x/Draw.c @@ -928,6 +928,11 @@ static PyObject *Method_Register( PyObject * self, PyObject * args ) Script *script; int startspace = 0; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Register() in background mode." ); + } + if( !PyArg_ParseTuple ( args, "O|OO", &newdrawc, &neweventc, &newbuttonc ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1008,6 +1013,10 @@ static PyObject *Method_Redraw( PyObject * self, PyObject * args ) { int after = 0; + if (G.background) { + Py_RETURN_NONE; + } + if( !PyArg_ParseTuple( args, "|i", &after ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected int argument (or nothing)" ); @@ -1022,6 +1031,10 @@ static PyObject *Method_Redraw( PyObject * self, PyObject * args ) static PyObject *Method_Draw( PyObject * self ) { + if (G.background) { + Py_RETURN_NONE; + } + /*@ If forced drawing is disable queue a redraw event instead */ if( EXPP_disable_force_draw ) { scrarea_queue_winredraw( curarea ); @@ -1089,6 +1102,11 @@ static PyObject *Method_UIBlock( PyObject * self, PyObject * args ) PyObject *result = NULL; ListBase listb= {NULL, NULL}; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.UIBlock() in background mode." ); + } + if ( !PyArg_ParseTuple( args, "O", &val ) || !PyCallable_Check( val ) ) return EXPP_ReturnPyObjError( PyExc_AttributeError, "expected 1 python function and 2 ints" ); @@ -1201,6 +1219,11 @@ static PyObject *Method_Button( PyObject * self, PyObject * args ) int x, y, w, h; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Button() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiii|sO", &name, &event, &x, &y, &w, &h, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1225,6 +1248,11 @@ static PyObject *Method_Menu( PyObject * self, PyObject * args ) Button *but; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Menu() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiiii|sO", &name, &event, &x, &y, &w, &h, &def, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1255,6 +1283,11 @@ static PyObject *Method_Toggle( PyObject * self, PyObject * args ) Button *but; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Toggle() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiiii|sO", &name, &event, &x, &y, &w, &h, &def, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1322,6 +1355,11 @@ static PyObject *Method_Slider( PyObject * self, PyObject * args ) PyObject *mino, *maxo, *inio; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Sider() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiiiOOO|isO", &name, &event, &x, &y, &w, &h, &inio, &mino, &maxo, &realtime, &tip, &callback ) ) @@ -1395,6 +1433,11 @@ static PyObject *Method_Scrollbar( PyObject * self, PyObject * args ) float ini, min, max; uiBut *ubut; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Scrollbar() in background mode." ); + } + if( !PyArg_ParseTuple( args, "iiiiiOOO|isO", &event, &x, &y, &w, &h, &inio, &mino, &maxo, &realtime, &tip ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1454,6 +1497,11 @@ static PyObject *Method_ColorPicker( PyObject * self, PyObject * args ) short x, y, w, h; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.ColorPicker() in background mode." ); + } + if( !PyArg_ParseTuple( args, "ihhhhO!|sO", &event, &x, &y, &w, &h, &PyTuple_Type, &inio, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1504,6 +1552,11 @@ static PyObject *Method_Normal( PyObject * self, PyObject * args ) short x, y, w, h; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Normal() in background mode." ); + } + if( !PyArg_ParseTuple( args, "ihhhhO!|sO", &event, &x, &y, &w, &h, &PyTuple_Type, &inio, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1546,6 +1599,11 @@ static PyObject *Method_Number( PyObject * self, PyObject * args ) PyObject *callback=NULL; uiBut *ubut= NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Number() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiiiOOO|sO", &name, &event, &x, &y, &w, &h, &inio, &mino, &maxo, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1617,6 +1675,11 @@ static PyObject *Method_String( PyObject * self, PyObject * args ) Button *but; PyObject *callback=NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.String() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiiiisi|sO", &info_arg, &event, &x, &y, &w, &h, &newstr, &len, &tip, &callback ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1693,6 +1756,11 @@ static PyObject *Method_Text( PyObject * self, PyObject * args ) char *font_str = NULL; struct BMF_Font *font; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Text() in background mode." ); + } + if( !PyArg_ParseTuple( args, "s|s", &text, &font_str ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected one or two string arguments" ); @@ -1724,6 +1792,11 @@ static PyObject *Method_Label( PyObject * self, PyObject * args ) char *text; int x, y, w, h; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Label() in background mode." ); + } + if( !PyArg_ParseTuple( args, "siiii", &text, &x, &y, &w, &h ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a string and four ints" ); @@ -1740,7 +1813,12 @@ static PyObject *Method_PupMenu( PyObject * self, PyObject * args ) char *text; int maxrow = -1; PyObject *ret; - + + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupMenu() in background mode." ); + } + if( !PyArg_ParseTuple( args, "s|i", &text, &maxrow ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a string and optionally an int as arguments" ); @@ -1827,6 +1905,11 @@ static PyObject *Method_PupTreeMenu( PyObject * self, PyObject * args ) ListBase storage = {NULL, NULL}; TBitem *tb; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupMenuTree() in background mode." ); + } + if( !PyArg_ParseTuple( args, "O!", &PyList_Type, ¤t_menu ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "Expected a list" ); @@ -1857,6 +1940,11 @@ static PyObject *Method_PupIntInput( PyObject * self, PyObject * args ) short var = 0; PyObject *ret = NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupIntInput() in background mode." ); + } + if( !PyArg_ParseTuple( args, "s|hii", &text, &var, &min, &max ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected 1 string and 3 int arguments" ); @@ -1879,6 +1967,11 @@ static PyObject *Method_PupFloatInput( PyObject * self, PyObject * args ) float min = 0, max = 1, var = 0, a1 = 10, a2 = 2; PyObject *ret = NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupFloatInput() in background mode." ); + } + if( !PyArg_ParseTuple ( args, "s|fffff", &text, &var, &min, &max, &a1, &a2 ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, @@ -1903,6 +1996,11 @@ static PyObject *Method_PupStrInput( PyObject * self, PyObject * args ) char max = 20; PyObject *ret = NULL; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupStrInput() in background mode." ); + } + if( !PyArg_ParseTuple( args, "ss|b", &textMsg, &text, &max ) ) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected 2 strings and 1 int" ); @@ -1937,6 +2035,11 @@ static PyObject *Method_PupBlock( PyObject * self, PyObject * args ) int len, i; char *title; + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.PupBlock() in background mode." ); + } + if (!PyArg_ParseTuple( args, "sO", &title, &pyList ) || !PySequence_Check( pyList )) return EXPP_ReturnPyObjError( PyExc_TypeError, "expected a string and a sequence" ); @@ -2070,6 +2173,11 @@ static PyObject *Method_Image( PyObject * self, PyObject * args ) int clipX = 0, clipY = 0, clipW = -1, clipH = -1; /*GLfloat scissorBox[4];*/ + if (G.background) { + return EXPP_ReturnPyObjError( PyExc_RuntimeError, + "Can't run Draw.Image() in background mode." ); + } + /* parse the arguments passed-in from Python */ if( !PyArg_ParseTuple( args, "O!ff|ffiiii", &Image_Type, &pyObjImage, &originX, &originY, &zoomX, &zoomY, diff --git a/source/blender/python/api2_2x/Window.c b/source/blender/python/api2_2x/Window.c index fe789fb4811..41a4e4e215f 100644 --- a/source/blender/python/api2_2x/Window.c +++ b/source/blender/python/api2_2x/Window.c @@ -1249,9 +1249,10 @@ static PyObject *M_Window_TestBreak( PyObject * self ) static PyObject *M_Window_GetMouseCoords( PyObject * self ) { - short mval[2]; + short mval[2] = {0, 0}; - getmouse( mval ); + if (!G.background) + getmouse( mval ); return Py_BuildValue( "hh", mval[0], mval[1] ); } @@ -1283,16 +1284,12 @@ static PyObject *M_Window_SetMouseCoords( PyObject * self, PyObject * args ) static PyObject *M_Window_GetMouseButtons( PyObject * self ) { - short mbut = get_mbut( ); - - return Py_BuildValue( "h", mbut ); + return PyInt_FromLong(G.background ? 0 : (int)get_mbut() ); } static PyObject *M_Window_GetKeyQualifiers( PyObject * self ) { - short qual = get_qual( ); - - return Py_BuildValue( "h", qual ); + return PyInt_FromLong( (int)get_qual() ); } static PyObject *M_Window_SetKeyQualifiers( PyObject * self, PyObject * args ) diff --git a/source/blender/python/api2_2x/bpy_data.c b/source/blender/python/api2_2x/bpy_data.c index 4705c1bdd03..b625f60e2da 100644 --- a/source/blender/python/api2_2x/bpy_data.c +++ b/source/blender/python/api2_2x/bpy_data.c @@ -263,9 +263,12 @@ PyObject *LibBlockSeq_getActive(BPy_LibBlockSeq *self) } break; case ID_TXT: { - SpaceText *st= curarea->spacedata.first; + SpaceText *st = NULL; - if (st->spacetype!=SPACE_TEXT || st->text==NULL) { + if (curarea) + st = curarea->spacedata.first; + + if (st==NULL || st->spacetype!=SPACE_TEXT || st->text==NULL) { Py_RETURN_NONE; } else { return Text_CreatePyObject( st->text ); @@ -330,7 +333,14 @@ static int LibBlockSeq_setActive(BPy_LibBlockSeq *self, PyObject *value) return EXPP_ReturnIntError(PyExc_TypeError, "Must be a text" ); } else { - SpaceText *st= curarea->spacedata.first; + SpaceText *st= NULL; + + if (curarea==NULL) { + return 0; + } else { + st= curarea->spacedata.first; + } + Text *data = ((BPy_Text *)value)->text; if( !data ) From b25d0cc5cc7bfa7ce9f668cdba77e9b3f3238d3f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 14 Sep 2008 05:42:05 +0000 Subject: [PATCH 058/125] game engine didnt compile with recent keyframing changes --- source/gameengine/Converter/KX_BlenderSceneConverter.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 2ce325326a8..b05893da4e1 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -662,11 +662,11 @@ extern "C" char *getIpoCurveName( IpoCurve * icu ); struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int); void testhandles_ipocurve(struct IpoCurve *icu); + void insert_vert_icu(struct IpoCurve *, float, float, short); void Mat3ToEul(float tmat[][3], float *eul); - } -IpoCurve* findIpoCurve(IpoCurve* first,char* searchName) +IpoCurve* findIpoCurve(IpoCurve* first, const char* searchName) { IpoCurve* icu1; for( icu1 = first; icu1; icu1 = icu1->next ) From 375a6bbe415388866a43f86b935fb9b1fccf994b Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 14 Sep 2008 05:52:57 +0000 Subject: [PATCH 059/125] More bugfixes: * Added missing includes * Fixed typos in header * Added code to get ipo for 'Available' keyingsets to work --- source/blender/include/BIF_keyframing.h | 2 +- source/blender/src/buttons_object.c | 1 + source/blender/src/drawaction.c | 1 + source/blender/src/editkey.c | 1 + source/blender/src/keyframing.c | 17 ++++++++++++----- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/source/blender/include/BIF_keyframing.h b/source/blender/include/BIF_keyframing.h index 9ade4f74b92..eeaef957b90 100644 --- a/source/blender/include/BIF_keyframing.h +++ b/source/blender/include/BIF_keyframing.h @@ -1,5 +1,5 @@ /** - * $Id: BDR_gpencil.h 14444 2008*04*16 22:40:48Z aligorith $ + * $Id: BIF_keyframing.h 14444 2008-04-16 22:40:48Z aligorith $ * * ***** BEGIN GPL LICENSE BLOCK ***** * diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index bb2beaae820..71e5ff6c10e 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -66,6 +66,7 @@ #include "BIF_glutil.h" #include "BIF_graphics.h" #include "BIF_interface.h" +#include "BIF_keyframing.h" #include "BIF_keyval.h" #include "BIF_mainqueue.h" #include "BIF_mywindow.h" diff --git a/source/blender/src/drawaction.c b/source/blender/src/drawaction.c index 33eb5262c3d..f36719a1c9c 100644 --- a/source/blender/src/drawaction.c +++ b/source/blender/src/drawaction.c @@ -78,6 +78,7 @@ #include "BIF_drawgpencil.h" #include "BIF_gl.h" #include "BIF_glutil.h" +#include "BIF_keyframing.h" #include "BIF_resources.h" #include "BIF_screen.h" #include "BIF_mywindow.h" diff --git a/source/blender/src/editkey.c b/source/blender/src/editkey.c index ce798064632..cf12e171a9c 100644 --- a/source/blender/src/editkey.c +++ b/source/blender/src/editkey.c @@ -70,6 +70,7 @@ #include "BIF_editkey.h" #include "BIF_editview.h" +#include "BIF_keyframing.h" #include "BIF_mywindow.h" #include "BIF_screen.h" #include "BIF_space.h" diff --git a/source/blender/src/keyframing.c b/source/blender/src/keyframing.c index b2fad5e85ce..fd9b19cc3b0 100644 --- a/source/blender/src/keyframing.c +++ b/source/blender/src/keyframing.c @@ -1284,7 +1284,6 @@ static void commonkey_context_getv3d (ListBase *sources, bKeyingContext **ksc) } /* helper for commonkey_context_get() - get keyingsets for buttons window */ -// nb - for mtex entries... need to set map (= texchan_to_adrcode(id->texact) static void commonkey_context_getsbuts (ListBase *sources, bKeyingContext **ksc) { bCommonKeySrc *cks; @@ -1304,6 +1303,7 @@ static void commonkey_context_getsbuts (ListBase *sources, bKeyingContext **ksc) /* set data */ cks->id= (ID *)ma; + cks->ipo= ma->ipo; cks->map= texchannel_to_adrcode(ma->texact); /* set keyingsets */ @@ -1321,6 +1321,7 @@ static void commonkey_context_getsbuts (ListBase *sources, bKeyingContext **ksc) /* set data */ cks->id= (ID *)wo; + cks->ipo= wo->ipo; cks->map= texchannel_to_adrcode(wo->texact); /* set keyingsets */ @@ -1338,6 +1339,7 @@ static void commonkey_context_getsbuts (ListBase *sources, bKeyingContext **ksc) /* set data */ cks->id= (ID *)la; + cks->ipo= la->ipo; cks->map= texchannel_to_adrcode(la->texact); /* set keyingsets */ @@ -1347,14 +1349,15 @@ static void commonkey_context_getsbuts (ListBase *sources, bKeyingContext **ksc) break; case TAB_SHADING_TEX: /* >------------- Texture Tab -------------< */ { - Tex *te= G.buts->lockpoin; + Tex *tex= G.buts->lockpoin; /* add new keyframing destination */ cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); BLI_addtail(sources, cks); /* set data */ - cks->id= (ID *)te; + cks->id= (ID *)tex; + cks->ipo= tex->ipo; /* set keyingsets */ *ksc= &ks_contexts[KSC_BUTS_TEX]; @@ -1375,6 +1378,7 @@ static void commonkey_context_getsbuts (ListBase *sources, bKeyingContext **ksc) /* set id-block to key to */ cks->id= (ID *)ob; + cks->ipo= ob->ipo; /* set keyingsets */ *ksc= &ks_contexts[KSC_BUTS_OB]; @@ -1387,13 +1391,16 @@ static void commonkey_context_getsbuts (ListBase *sources, bKeyingContext **ksc) { Object *ob= OBACT; - if ((ob) && (ob->type==OB_CAMERA)) { /* >---------------- camera buttons ---------------< */ + if ((ob) && (ob->type==OB_CAMERA) && (G.buts->lockpoin)) { /* >---------------- camera buttons ---------------< */ + Camera *ca= G.buts->lockpoin; + /* add new keyframing destination */ cks= MEM_callocN(sizeof(bCommonKeySrc), "bCommonKeySrc"); BLI_addtail(sources, cks); /* set id-block to key to */ - cks->id= (ID *)ob; + cks->id= (ID *)ca; + cks->ipo= ca->ipo; /* set keyingsets */ *ksc= &ks_contexts[KSC_BUTS_CAM]; From 2bf26b93e12de1382850712551ea7203c5b80692 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sun, 14 Sep 2008 09:09:10 +0000 Subject: [PATCH 060/125] Bugfix #17608 Fileselect window: Pressing X to remove a file should not work in databrowse view. --- source/blender/src/filesel.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/source/blender/src/filesel.c b/source/blender/src/filesel.c index 2ba5745b19b..cdb001d9193 100644 --- a/source/blender/src/filesel.c +++ b/source/blender/src/filesel.c @@ -2062,18 +2062,20 @@ void winqreadfilespace(ScrArea *sa, void *spacedata, BWinEvent *evt) break; case XKEY: - test = get_hilited_entry(sfile); + if(sfile->type==FILE_BLENDER) { + test = get_hilited_entry(sfile); - if (test != -1 && !(S_ISDIR(sfile->filelist[test].type))){ - BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[test].relname); + if (test != -1 && !(S_ISDIR(sfile->filelist[test].type))){ + BLI_make_file_string(G.sce, str, sfile->dir, sfile->filelist[test].relname); - if( okee("Remove %s", str) ) { - ret = BLI_delete(str, 0, 0); - if (ret) { - error("Command failed, see console"); - } else { - freefilelist(sfile); - do_draw= 1; + if( okee("Remove %s", str) ) { + ret = BLI_delete(str, 0, 0); + if (ret) { + error("Command failed, see console"); + } else { + freefilelist(sfile); + do_draw= 1; + } } } } From 4245aaed86dad24395d8b863832be23fcb85ae4e Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Sun, 14 Sep 2008 12:41:42 +0000 Subject: [PATCH 061/125] == Global 'Delete Key' Tool == The 'opposite' of the "Insert Key" tool. - Use the hotkey Ctrl-Alt-IKEY to activate. - Only available in 3d-view and buttons window I've added an extra var to verify_ipo and verify_ipocurve to save having to make another duplicate of that code. Hopefully the gameengine compiles ok with this. --- .../blenkernel/bad_level_call_stubs/stubs.c | 4 +- source/blender/include/BSE_editipo.h | 4 +- source/blender/python/api2_2x/Constraint.c | 2 +- source/blender/python/api2_2x/Object.c | 2 +- source/blender/src/buttons_object.c | 8 +- source/blender/src/drawipo.c | 2 +- source/blender/src/editaction.c | 2 +- source/blender/src/editipo.c | 183 ++++++++++-------- source/blender/src/editkey.c | 4 +- source/blender/src/keyframing.c | 54 +++++- source/blender/src/toets.c | 4 + .../Converter/KX_BlenderSceneConverter.cpp | 26 +-- 12 files changed, 179 insertions(+), 116 deletions(-) diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index d7ef5cb54ff..f4beca262d7 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -60,7 +60,7 @@ struct EditFace; char *getIpoCurveName( struct IpoCurve * icu ); void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast); -struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e); +struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e, short f); void elbeemDebugOut(char *msg); void fluidsimSettingsFree(struct FluidsimSettings* sb); void fluidsimSettingsCopy(struct FluidsimSettings* sb); @@ -88,7 +88,7 @@ void insert_vert_icu(struct IpoCurve *icu, float x, float y, short fast) } -struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e) +struct IpoCurve *verify_ipocurve(struct ID *id, short a, char *b, char *d, int e, short f) { return 0; } diff --git a/source/blender/include/BSE_editipo.h b/source/blender/include/BSE_editipo.h index b7b19a373aa..807e338f514 100644 --- a/source/blender/include/BSE_editipo.h +++ b/source/blender/include/BSE_editipo.h @@ -86,8 +86,8 @@ void do_ipo_selectbuttons(void); /* gets ipo curve, creates if needed */ -struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int); -struct Ipo *verify_ipo(struct ID *, short, char *, char *, char *); +struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int, short); +struct Ipo *verify_ipo(struct ID *, short, char *, char *, char *, short); int texchannel_to_adrcode(int channel); diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c index 156d32d55c0..b0b9aa04a08 100644 --- a/source/blender/python/api2_2x/Constraint.c +++ b/source/blender/python/api2_2x/Constraint.c @@ -442,7 +442,7 @@ static PyObject *Constraint_insertKey( BPy_Constraint * self, PyObject * value ) return EXPP_ReturnPyObjError( PyExc_RuntimeError, "constraint doesn't belong to anything" ); } - icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, NULL, CO_ENFORCE); + icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, NULL, CO_ENFORCE, 1); if (!icu) return EXPP_ReturnPyObjError( PyExc_RuntimeError, diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index a9cbd1c7766..45d6bfa3c01 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -2735,7 +2735,7 @@ static PyObject *Object_setConstraintInfluenceForBone( BPy_Object * self, "expects bonename, constraintname, influenceval" ); icu = verify_ipocurve((ID *)self->object, ID_CO, boneName, constName, NULL, - CO_ENFORCE); + CO_ENFORCE, 1); if (!icu) return EXPP_ReturnPyObjError( PyExc_RuntimeError, diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 71e5ff6c10e..c1af6c2d00c 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -242,9 +242,9 @@ static void enable_constraint_ipo_func (void *ob_v, void *con_v) /* adds ipo & channels & curve if needed */ if(con->flag & CONSTRAINT_OWN_IPO) - verify_ipo((ID *)ob, ID_CO, NULL, con->name, actname); + verify_ipo((ID *)ob, ID_CO, NULL, con->name, actname, 1); else - verify_ipo((ID *)ob, ID_CO, actname, con->name, NULL); + verify_ipo((ID *)ob, ID_CO, actname, con->name, NULL, 1); /* make sure ipowin shows it */ ob->ipowin= ID_CO; @@ -269,9 +269,9 @@ static void add_influence_key_to_constraint_func (void *ob_v, void *con_v) /* adds ipo & channels & curve if needed */ if(con->flag & CONSTRAINT_OWN_IPO) - icu= verify_ipocurve((ID *)ob, ID_CO, NULL, con->name, actname, CO_ENFORCE); + icu= verify_ipocurve((ID *)ob, ID_CO, NULL, con->name, actname, CO_ENFORCE, 1); else - icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, NULL, CO_ENFORCE); + icu= verify_ipocurve((ID *)ob, ID_CO, actname, con->name, NULL, CO_ENFORCE, 1); if (!icu) { error("Cannot get a curve from this IPO, may be dealing with linked data"); diff --git a/source/blender/src/drawipo.c b/source/blender/src/drawipo.c index 87e36c4ad24..ec6a0f0d75b 100644 --- a/source/blender/src/drawipo.c +++ b/source/blender/src/drawipo.c @@ -1952,7 +1952,7 @@ void do_ipobuts(unsigned short event) ei= get_active_editipo(); if(ei) { if(ei->icu==NULL) { - ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode); + ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1); if (!ei->icu) { error("Could not add a driver to this curve, may be linked data!"); break; diff --git a/source/blender/src/editaction.c b/source/blender/src/editaction.c index 95a69171bf8..fe83976ee57 100644 --- a/source/blender/src/editaction.c +++ b/source/blender/src/editaction.c @@ -2154,7 +2154,7 @@ void paste_actdata () /* loop over curves, pasting keyframes */ for (ico= ipo_src->curve.first; ico; ico= ico->next) { - icu= verify_ipocurve((ID*)ob, ico->blocktype, actname, conname, "", ico->adrcode); + icu= verify_ipocurve((ID*)ob, ico->blocktype, actname, conname, "", ico->adrcode, 1); if (icu) { /* just start pasting, with the the first keyframe on the current frame, and so on */ diff --git a/source/blender/src/editipo.c b/source/blender/src/editipo.c index e6c7e155a0f..09862636085 100644 --- a/source/blender/src/editipo.c +++ b/source/blender/src/editipo.c @@ -1777,113 +1777,129 @@ void do_ipo_selectbuttons(void) - if bonename, the constname is the ipo to the constraint */ -/* note; check header_ipo.c, spaceipo_assign_ipo() too */ -Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char *bonename) +/* note: check header_ipo.c, spaceipo_assign_ipo() too */ +Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char *bonename, short add) { - - if(from==NULL || from->lib) return NULL; + /* lib-linked data is not appropriate here */ + if ((from==NULL) || (from->lib)) + return NULL; /* first check action ipos */ - if(actname && actname[0]) { + if (actname && actname[0]) { Object *ob= (Object *)from; bActionChannel *achan; - if(GS(from->name)!=ID_OB) { + if (GS(from->name)!=ID_OB) { printf("called ipo system for action with wrong base pointer\n"); return NULL; } - if(ob->action==NULL) + if ((ob->action==NULL) && (add)) ob->action= add_empty_action("Action"); - achan= verify_action_channel(ob->action, actname); + if (add) + achan= verify_action_channel(ob->action, actname); + else + achan= get_action_channel(ob->action, actname); - if(achan) { + if (achan) { /* automatically assign achan to act-group based on pchan's grouping */ - if (blocktype == ID_PO) + if ((blocktype == ID_PO) && (add)) verify_pchan2achan_grouping(ob->action, ob->pose, actname); /* constraint exception */ - if(blocktype==ID_CO) { - bConstraintChannel *conchan= verify_constraint_channel(&achan->constraintChannels, constname); - if(conchan->ipo==NULL) { - conchan->ipo= add_ipo("CoIpo", ID_CO); + if (blocktype==ID_CO) { + bConstraintChannel *conchan; + + if (add) + conchan= verify_constraint_channel(&achan->constraintChannels, constname); + else + conchan= get_constraint_channel(&achan->constraintChannels, constname); + + if (conchan) { + if ((conchan->ipo==NULL) && (add)) + conchan->ipo= add_ipo("CoIpo", ID_CO); + return conchan->ipo; } - return conchan->ipo; } else { - if(achan->ipo==NULL) { + if ((achan->ipo==NULL) && (add)) achan->ipo= add_ipo("ActIpo", blocktype); - } - return achan->ipo; } } } else { - - switch(GS(from->name)) { + switch (GS(from->name)) { case ID_OB: { Object *ob= (Object *)from; /* constraint exception */ - if(blocktype==ID_CO) { + if (blocktype==ID_CO) { /* check the local constraint ipo */ - if(bonename && bonename[0] && ob->pose) { + if (bonename && bonename[0] && ob->pose) { bPoseChannel *pchan= get_pose_channel(ob->pose, bonename); bConstraint *con; - for(con= pchan->constraints.first; con; con= con->next) - if(strcmp(con->name, constname)==0) + + for (con= pchan->constraints.first; con; con= con->next) { + if (strcmp(con->name, constname)==0) break; - if(con) { - if(con->ipo==NULL) { + } + + if (con) { + if ((con->ipo==NULL) && (add)) con->ipo= add_ipo("CoIpo", ID_CO); - } return con->ipo; } } else { /* the actionchannel */ - bConstraintChannel *conchan= verify_constraint_channel(&ob->constraintChannels, constname); - if(conchan->ipo==NULL) { - conchan->ipo= add_ipo("CoIpo", ID_CO); + bConstraintChannel *conchan; + + if (add) + conchan= verify_constraint_channel(&ob->constraintChannels, constname); + else + conchan= get_constraint_channel(&ob->constraintChannels, constname); + + if (conchan) { + if ((conchan->ipo==NULL) && (add)) + conchan->ipo= add_ipo("CoIpo", ID_CO); + return conchan->ipo; } - return conchan->ipo; } } - else if(blocktype==ID_OB) { - if(ob->ipo==NULL) { + else if (blocktype==ID_OB) { + if ((ob->ipo==NULL) && (add)) ob->ipo= add_ipo("ObIpo", ID_OB); - } return ob->ipo; } - else if(blocktype==ID_KE) { + else if (blocktype==ID_KE) { Key *key= ob_get_key((Object *)from); - if(key) { - if(key->ipo==NULL) { + if (key) { + if ((key->ipo==NULL) && (add)) key->ipo= add_ipo("KeyIpo", ID_KE); - } return key->ipo; } return NULL; } - else if(blocktype== ID_FLUIDSIM) { + else if (blocktype== ID_FLUIDSIM) { Object *ob= (Object *)from; - if(ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) { + + if (ob->fluidsimFlag & OB_FLUIDSIM_ENABLE) { FluidsimSettings *fss= ob->fluidsimSettings; - if(fss->ipo==NULL) { + + if ((fss->ipo==NULL) && (add)) fss->ipo= add_ipo("FluidsimIpo", ID_FLUIDSIM); - //fprintf(stderr,"FSIPO NEW!\n"); - } return fss->ipo; } } - else if(blocktype== ID_PA){ + else if(blocktype== ID_PA) { Object *ob= (Object *)from; ParticleSystem *psys= psys_get_current(ob); - if(psys){ - if(psys->part->ipo==0) + + if (psys) { + if ((psys->part->ipo==NULL) && (add)) psys->part->ipo= add_ipo("ParticleIpo", ID_PA); return psys->part->ipo; } @@ -1894,30 +1910,27 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char case ID_MA: { Material *ma= (Material *)from; - - if(ma->ipo==NULL) { + + if ((ma->ipo==NULL) && (add)) ma->ipo= add_ipo("MatIpo", ID_MA); - } return ma->ipo; } break; case ID_TE: { Tex *tex= (Tex *)from; - - if(tex->ipo==NULL) { + + if ((tex->ipo==NULL) && (add)) tex->ipo= add_ipo("TexIpo", ID_TE); - } return tex->ipo; } break; case ID_SEQ: { Sequence *seq= (Sequence *)from; /* note, sequence is mimicing Id */ - - if(seq->ipo==NULL) { + + if ((seq->ipo==NULL) && (add)) seq->ipo= add_ipo("SeqIpo", ID_SEQ); - } update_seq_ipo_rect(seq); return seq->ipo; } @@ -1926,19 +1939,17 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char { Curve *cu= (Curve *)from; - if(cu->ipo==NULL) { + if ((cu->ipo==NULL) && (add)) cu->ipo= add_ipo("CuIpo", ID_CU); - } return cu->ipo; } break; case ID_WO: { World *wo= (World *)from; - - if(wo->ipo==NULL) { + + if ((wo->ipo==NULL) && (add)) wo->ipo= add_ipo("WoIpo", ID_WO); - } return wo->ipo; } break; @@ -1946,29 +1957,26 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char { Lamp *la= (Lamp *)from; - if(la->ipo==NULL) { + if ((la->ipo==NULL) && (add)) la->ipo= add_ipo("LaIpo", ID_LA); - } return la->ipo; } break; case ID_CA: { Camera *ca= (Camera *)from; - - if(ca->ipo==NULL) { + + if ((ca->ipo==NULL) && (add)) ca->ipo= add_ipo("CaIpo", ID_CA); - } return ca->ipo; } break; case ID_SO: { bSound *snd= (bSound *)from; - - if(snd->ipo==NULL) { + + if ((snd->ipo==NULL) && (add)) snd->ipo= add_ipo("SndIpo", ID_SO); - } return snd->ipo; } } @@ -1980,32 +1988,36 @@ Ipo *verify_ipo(ID *from, short blocktype, char *actname, char *constname, char /* returns and creates * Make sure functions check for NULL or they will crash! * */ -IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constname, char *bonename, int adrcode) +IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constname, char *bonename, int adrcode, short add) { Ipo *ipo; IpoCurve *icu= NULL; /* return 0 if lib */ - /* creates ipo too */ - ipo= verify_ipo(from, blocktype, actname, constname, bonename); + /* creates ipo too (if add) */ + ipo= verify_ipo(from, blocktype, actname, constname, bonename, add); - if(ipo && ipo->id.lib==NULL && from->lib==NULL) { - - for(icu= ipo->curve.first; icu; icu= icu->next) { - if(icu->adrcode==adrcode) break; + if (ipo && ipo->id.lib==NULL && from->lib==NULL) { + /* try to find matching curve */ + for (icu= ipo->curve.first; icu; icu= icu->next) { + if (icu->adrcode==adrcode) + break; } - if(icu==NULL) { + + /* make a new one if none found (and can add) */ + if ((icu==NULL) && (add)) { icu= MEM_callocN(sizeof(IpoCurve), "ipocurve"); - icu->flag |= IPO_VISIBLE|IPO_AUTO_HORIZ; - if(ipo->curve.first==NULL) icu->flag |= IPO_ACTIVE; /* first one added active */ + icu->flag |= (IPO_VISIBLE|IPO_AUTO_HORIZ); + if (ipo->curve.first==NULL) + icu->flag |= IPO_ACTIVE; /* first one added active */ icu->blocktype= blocktype; icu->adrcode= adrcode; set_icu_vars(icu); - BLI_addtail( &(ipo->curve), icu); + BLI_addtail(&ipo->curve, icu); switch (GS(from->name)) { case ID_SEQ: { @@ -2017,7 +2029,8 @@ IpoCurve *verify_ipocurve(ID *from, short blocktype, char *actname, char *constn } } } - + + /* return ipo-curve */ return icu; } @@ -2055,7 +2068,7 @@ void add_vert_ipo(void) if(ei->icu==NULL) { if(G.sipo->from) { - ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode); + ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1); if (ei->icu) ei->flag |= ei->icu->flag & IPO_AUTO_HORIZ; /* new curve could have been added, weak... */ else @@ -3185,7 +3198,7 @@ void paste_editipo(void) int i; /* make sure an ipo-curve exists (it may not, as this is an editipo) */ - ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode); + ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1); if (ei->icu == NULL) return; /* Copy selected beztriples from source icu onto this edit-icu, @@ -3226,7 +3239,7 @@ void paste_editipo(void) else { /* make sure an ipo-curve exists (it may not, as this is an editipo) */ - ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode); + ei->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei->adrcode, 1); if (ei->icu==NULL) return; /* clear exisiting dynamic memory (keyframes, driver) */ @@ -4341,7 +4354,7 @@ void ipo_record(void) /* make curves ready, start values */ if(ei1->icu==NULL) - ei1->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei1->adrcode); + ei1->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei1->adrcode, 1); if(ei1->icu==NULL) return; poin= get_ipo_poin(G.sipo->from, ei1->icu, &type); @@ -4351,7 +4364,7 @@ void ipo_record(void) if(ei2) { if(ei2->icu==NULL) - ei2->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei2->adrcode); + ei2->icu= verify_ipocurve(G.sipo->from, G.sipo->blocktype, G.sipo->actname, G.sipo->constname, G.sipo->bonename, ei2->adrcode, 1); if(ei2->icu==NULL) return; poin= get_ipo_poin(G.sipo->from, ei2->icu, &type); diff --git a/source/blender/src/editkey.c b/source/blender/src/editkey.c index cf12e171a9c..dbabf9d19fb 100644 --- a/source/blender/src/editkey.c +++ b/source/blender/src/editkey.c @@ -171,9 +171,9 @@ static void rvk_slider_func(void *voidob, void *voidkeynum) /* ipo on action or ob? */ if(ob->ipoflag & OB_ACTION_KEY) - icu = verify_ipocurve(&ob->id, ID_KE, "Shape", NULL, NULL, keynum); + icu = verify_ipocurve(&ob->id, ID_KE, "Shape", NULL, NULL, keynum, 1); else - icu = verify_ipocurve(&ob->id, ID_KE, NULL, NULL, NULL, keynum); + icu = verify_ipocurve(&ob->id, ID_KE, NULL, NULL, NULL, keynum, 1); if (icu) { /* if the ipocurve exists, try to get a bezier diff --git a/source/blender/src/keyframing.c b/source/blender/src/keyframing.c index fd9b19cc3b0..80d4ebffec9 100644 --- a/source/blender/src/keyframing.c +++ b/source/blender/src/keyframing.c @@ -723,7 +723,7 @@ short insertkey (ID *id, int blocktype, char *actname, char *constname, int adrc IpoCurve *icu; /* get ipo-curve */ - icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode); + icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 1); /* only continue if we have an ipo-curve to add keyframe to */ if (icu) { @@ -815,12 +815,58 @@ short insertkey (ID *id, int blocktype, char *actname, char *constname, int adrc */ short deletekey (ID *id, int blocktype, char *actname, char *constname, int adrcode, short flag) { + Ipo *ipo; IpoCurve *icu; - // locate ipo-curve - icu= NULL; // fixme.. + /* get ipo-curve + * Note: here is one of the places where we don't want new ipo + ipo-curve added! + * so 'add' var must be 0 + */ + ipo= verify_ipo(id, blocktype, actname, constname, NULL, 0); + icu= verify_ipocurve(id, blocktype, actname, constname, NULL, adrcode, 0); - // TODO: implement me! + /* only continue if we have an ipo-curve to remove keyframes from */ + if (icu) { + BezTriple bezt; + float cfra = frame_to_float(CFRA); + short found = -1; + int i; + + /* apply special time tweaking */ + if (GS(id->name) == ID_OB) { + Object *ob= (Object *)id; + + /* apply NLA-scaling (if applicable) */ + if (actname && actname[0]) + cfra= get_action_frame(ob, cfra); + + /* ancient time-offset cruft */ + if ( (ob->ipoflag & OB_OFFS_OB) && (give_timeoffset(ob)) ) { + /* actually frametofloat calc again! */ + cfra-= give_timeoffset(ob)*G.scene->r.framelen; + } + } + + /* only need to set bezt->vec[1][0], as that's all binarysearch uses */ + memset(&bezt, 0, sizeof(BezTriple)); + bezt.vec[1][0]= cfra; + + /* try to find index of beztriple to get rid of */ + i = binarysearch_bezt_index(icu->bezt, &bezt, icu->totvert, &found); + if (found) { + /* delete the key at the index (will sanity check + do recalc afterwards ) */ + delete_icu_key(icu, i, 1); + + /* Only delete curve too if there isn't an ipo-driver still hanging around on an empty curve */ + if (icu->totvert==0 && icu->driver==NULL) { + BLI_remlink(&ipo->curve, icu); + free_ipo_curve(icu); + } + + /* return success */ + return 1; + } + } /* return failure */ return 0; diff --git a/source/blender/src/toets.c b/source/blender/src/toets.c index 8bd10b7186d..41ee557c9c2 100644 --- a/source/blender/src/toets.c +++ b/source/blender/src/toets.c @@ -793,6 +793,10 @@ int blenderqread(unsigned short event, short val) ob= OBACT; if(G.f & G_SCULPTMODE) return 1; + else if(G.qual==(LR_CTRLKEY|LR_ALTKEY)) { + common_deletekey(); + return 0; + } else if(G.qual==0) { common_insertkey(); return 0; diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index b05893da4e1..7eec93dc402 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -660,7 +660,7 @@ extern "C" { Ipo *add_ipo( char *name, int idcode ); char *getIpoCurveName( IpoCurve * icu ); - struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int); + struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int, short); void testhandles_ipocurve(struct IpoCurve *icu); void insert_vert_icu(struct IpoCurve *, float, float, short); void Mat3ToEul(float tmat[][3], float *eul); @@ -873,27 +873,27 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) IpoCurve *icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1); @@ -1029,27 +1029,27 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() IpoCurve *icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1); icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"); if (!icu1) - icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z); + icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1); From 6977816ff3a1777906bb5f8f16d2bad3f983dc2c Mon Sep 17 00:00:00 2001 From: Ken Hughes Date: Sun, 14 Sep 2008 14:17:44 +0000 Subject: [PATCH 062/125] Python API ---------- Fix C90 mixed declarations and code. --- source/blender/python/api2_2x/bpy_data.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/blender/python/api2_2x/bpy_data.c b/source/blender/python/api2_2x/bpy_data.c index b625f60e2da..47232c6707a 100644 --- a/source/blender/python/api2_2x/bpy_data.c +++ b/source/blender/python/api2_2x/bpy_data.c @@ -334,6 +334,7 @@ static int LibBlockSeq_setActive(BPy_LibBlockSeq *self, PyObject *value) "Must be a text" ); } else { SpaceText *st= NULL; + Text *data = ((BPy_Text *)value)->text; if (curarea==NULL) { return 0; @@ -341,8 +342,6 @@ static int LibBlockSeq_setActive(BPy_LibBlockSeq *self, PyObject *value) st= curarea->spacedata.first; } - Text *data = ((BPy_Text *)value)->text; - if( !data ) return EXPP_ReturnIntError( PyExc_RuntimeError, "This object isn't linked to a Blender Text Object" ); From 2eb8eb4e7eedece1f3233aa0d9889993c8575d3e Mon Sep 17 00:00:00 2001 From: Andrea Weikert Date: Sun, 14 Sep 2008 16:22:03 +0000 Subject: [PATCH 063/125] Bugfix: avoid crash with too long pathname. --- source/gameengine/Converter/KX_ConvertActuators.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 799506aecaa..e8be8de95ed 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -74,6 +74,8 @@ #include "BKE_text.h" #include "BLI_blenlib.h" +#define FILE_MAX 240 // repeated here to avoid dependency from BKE_utildefines.h + #include "KX_NetworkMessageActuator.h" #ifdef WIN32 @@ -362,7 +364,7 @@ void BL_ConvertActuators(char* maggiename, if (soundact->sound) { /* Need to convert the samplename into absolute path * before checking if its loaded */ - char fullpath[sizeof(soundact->sound->name)]; + char fullpath[FILE_MAX]; /* dont modify soundact->sound->name, only change a copy */ BLI_strncpy(fullpath, soundact->sound->name, sizeof(fullpath)); From 9444b314dbf586772a2f5482a3057997648630f8 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 14 Sep 2008 17:19:59 +0000 Subject: [PATCH 064/125] fix for what looks like simple mistake, function wasnt returning any values (compiler warning) and the variable being checked to return a value was never assigned. --- source/blender/src/keyframing.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/src/keyframing.c b/source/blender/src/keyframing.c index 80d4ebffec9..2aac2f8c497 100644 --- a/source/blender/src/keyframing.c +++ b/source/blender/src/keyframing.c @@ -702,9 +702,11 @@ static float visualkey_get_value (ID *id, int blocktype, char *actname, char *co } /* as the function hasn't returned yet, try reading from poin */ - get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); + poin= get_context_ipo_poin(id, blocktype, actname, constname, icu, &vartype); if (poin) return read_ipo_poin(poin, vartype); + else + return 0.0; } From 0ad48b7332668d033fb4bcf91c0a443aef13d8b4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 14 Sep 2008 17:56:15 +0000 Subject: [PATCH 065/125] scons option for linking python statically - useful for building a more compatible blenderplayer, where most games python scripts only use builtin modules anyway. --- config/linux2-config.py | 2 ++ tools/Blender.py | 13 +++++++++---- tools/btools.py | 4 +++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/config/linux2-config.py b/config/linux2-config.py index fe4325361a8..36cbac6df10 100644 --- a/config/linux2-config.py +++ b/config/linux2-config.py @@ -6,10 +6,12 @@ BF_VERSE_INCLUDE = "#extern/verse/dist" BF_PYTHON = '/usr' BF_PYTHON_VERSION = '2.5' +WITH_BF_STATICPYTHON = 'false' BF_PYTHON_INC = '${BF_PYTHON}/include/python${BF_PYTHON_VERSION}' BF_PYTHON_BINARY = '${BF_PYTHON}/bin/python${BF_PYTHON_VERSION}' BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' #BF_PYTHON+'/lib/python'+BF_PYTHON_VERSION+'/config/libpython'+BF_PYTHON_VERSION+'.a' BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic'] +BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/libpython${BF_PYTHON_VERSION}.a' WITH_BF_OPENAL = 'true' BF_OPENAL = '/usr' diff --git a/tools/Blender.py b/tools/Blender.py index 2c982a0a46f..3f928ff8c97 100644 --- a/tools/Blender.py +++ b/tools/Blender.py @@ -129,6 +129,9 @@ def setup_staticlibs(lenv): if lenv['WITH_BF_STATICOPENGL']: statlibs += Split(lenv['BF_OPENGL_LIB_STATIC']) + if lenv['WITH_BF_STATICPYTHON']: + statlibs += Split(lenv['BF_PYTHON_LIB_STATIC']) + if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross'): libincs += Split(lenv['BF_PTHREADS_LIBPATH']) @@ -141,10 +144,12 @@ def setup_syslibs(lenv): lenv['BF_PNG_LIB'], lenv['BF_ZLIB_LIB'] ] - if lenv['BF_DEBUG']==1 and lenv['OURPLATFORM'] in ('win32-vc'): - syslibs.append(lenv['BF_PYTHON_LIB']+'_d') - else: - syslibs.append(lenv['BF_PYTHON_LIB']) + + if not lenv['WITH_BF_STATICPYTHON']: + if lenv['BF_DEBUG']==1 and lenv['OURPLATFORM'] in ('win32-vc'): + syslibs.append(lenv['BF_PYTHON_LIB']+'_d') + else: + syslibs.append(lenv['BF_PYTHON_LIB']) if lenv['WITH_BF_INTERNATIONAL']: syslibs += Split(lenv['BF_FREETYPE_LIB']) syslibs += Split(lenv['BF_GETTEXT_LIB']) diff --git a/tools/btools.py b/tools/btools.py index 3974d582640..afcc83d2002 100755 --- a/tools/btools.py +++ b/tools/btools.py @@ -27,7 +27,7 @@ def print_arguments(args, bc): def validate_arguments(args, bc): opts_list = [ - 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'BF_PYTHON_LINKFLAGS', + 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'BF_PYTHON_LINKFLAGS', 'WITH_BF_STATICPYTHON', 'BF_PYTHON_LIB_STATIC', 'WITH_BF_OPENAL', 'BF_OPENAL', 'BF_OPENAL_INC', 'BF_OPENAL_LIB', 'BF_OPENAL_LIBPATH', 'WITH_BF_SDL', 'BF_SDL', 'BF_SDL_INC', 'BF_SDL_LIB', 'BF_SDL_LIBPATH', 'BF_PTHREADS', 'BF_PTHREADS_INC', 'BF_PTHREADS_LIB', 'BF_PTHREADS_LIBPATH', @@ -144,8 +144,10 @@ def read_opts(cfg, args): ('BF_PYTHON_INC', 'include path for Python headers', ''), ('BF_PYTHON_BINARY', 'Path to the Python interpreter', ''), ('BF_PYTHON_LIB', 'Python library', ''), + ('BF_PYTHON_LIB_STATIC', 'Python static libraries', ''), ('BF_PYTHON_LIBPATH', 'Library path', ''), ('BF_PYTHON_LINKFLAGS', 'Python link flags', ''), + (BoolOption('WITH_BF_STATICPYTHON', 'Staticly link to python', 'false')), (BoolOption('BF_NO_ELBEEM', 'Disable Fluid Sim', 'false')), (BoolOption('WITH_BF_YAFRAY', 'Enable Yafray', 'true')), (BoolOption('WITH_BF_OPENAL', 'Use OpenAL if true', '')), From 59b202fc320a06de79787ef7b95f3c4ce2bc92d0 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 14 Sep 2008 17:59:22 +0000 Subject: [PATCH 066/125] Fix a game engine crash with mesh objects parented to an armature without vertex groups. --- .../Converter/BL_BlenderDataConversion.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 4851b7f9b08..19fb9d01cbf 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -783,9 +783,9 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* MT_Point2 uv20(0.0,0.0),uv21(0.0,0.0),uv22(0.0,0.0),uv23(0.0,0.0); unsigned int rgb0,rgb1,rgb2,rgb3 = 0; - MT_Vector3 no0, no1, no2, no3; MT_Point3 pt0, pt1, pt2, pt3; - MT_Vector4 tan0, tan1, tan2, tan3; + MT_Vector3 no0(0,0,0), no1(0,0,0), no2(0,0,0), no3(0,0,0); + MT_Vector4 tan0(0,0,0,0), tan1(0,0,0,0), tan2(0,0,0,0), tan3(0,0,0,0); /* get coordinates, normals and tangents */ pt0 = MT_Point3(mvert[mface->v1].co); @@ -807,8 +807,6 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* NormalShortToFloat(n3, mvert[mface->v4].no); no3 = n3; } - else - no3 = MT_Vector3(0.0, 0.0, 0.0); } else { float fno[3]; @@ -2186,16 +2184,16 @@ void BL_ConvertBlenderObjects(struct Main* maggie, for(oit=allblobj.begin(); oit!=allblobj.end(); oit++) { Object* blenderobj = *oit; - if (blenderobj->type==OB_MESH){ + if (blenderobj->type==OB_MESH) { Mesh *me = (Mesh*)blenderobj->data; if (me->dvert){ - KX_GameObject *obj = converter->FindGameObject(blenderobj); + BL_DeformableGameObject *obj = (BL_DeformableGameObject*)converter->FindGameObject(blenderobj); if (obj && blenderobj->parent && blenderobj->parent->type==OB_ARMATURE && blenderobj->partype==PARSKEL){ KX_GameObject *par = converter->FindGameObject(blenderobj->parent); - if (par) - ((BL_SkinDeformer*)(((BL_DeformableGameObject*)obj)->m_pDeformer))->SetArmature((BL_ArmatureObject*) par); + if (par && obj->m_pDeformer) + ((BL_SkinDeformer*)obj->m_pDeformer)->SetArmature((BL_ArmatureObject*) par); } } } From 7762100fcb84679348d4a01cc4aa0d9e52d3abc0 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sun, 14 Sep 2008 19:07:57 +0000 Subject: [PATCH 067/125] Update MSVC project and fix compilation problem in VS2003 with keyframing.c --- projectfiles_vc7/blender/src/BL_src.vcproj | 6 +++ source/blender/src/keyframing.c | 58 +++++++++++----------- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/projectfiles_vc7/blender/src/BL_src.vcproj b/projectfiles_vc7/blender/src/BL_src.vcproj index b20e1811f1d..80694690107 100644 --- a/projectfiles_vc7/blender/src/BL_src.vcproj +++ b/projectfiles_vc7/blender/src/BL_src.vcproj @@ -430,6 +430,9 @@ + + @@ -746,6 +749,9 @@ + + diff --git a/source/blender/src/keyframing.c b/source/blender/src/keyframing.c index 2aac2f8c497..19918a70a33 100644 --- a/source/blender/src/keyframing.c +++ b/source/blender/src/keyframing.c @@ -927,7 +927,7 @@ bKeyingSet defks_v3d_object[] = {NULL, "Rot", ID_OB, 0, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, {NULL, "Scale", ID_OB, 0, 3, {OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator {NULL, "LocRot", ID_OB, 0, 6, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, @@ -946,7 +946,7 @@ bKeyingSet defks_v3d_object[] = {OB_ROT_X,OB_ROT_Y,OB_ROT_Z, OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator {NULL, "VisualLoc", ID_OB, INSERTKEY_MATRIX, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}}, {NULL, "VisualRot", ID_OB, INSERTKEY_MATRIX, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, @@ -955,13 +955,13 @@ bKeyingSet defks_v3d_object[] = {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator {NULL, "Layer", ID_OB, 0, 1, {OB_LAY}}, // icky option... - {NULL, "Available", ID_OB, -2, 0, {}}, + {NULL, "Available", ID_OB, -2, 0, {0}}, - {incl_v3d_ob_shapekey, "%l%l", 0, -1, 0, {}}, // separator (linked to shapekey entry) - {incl_v3d_ob_shapekey, "", ID_OB, -3, 0, {}} + {incl_v3d_ob_shapekey, "%l%l", 0, -1, 0, {0}}, // separator (linked to shapekey entry) + {incl_v3d_ob_shapekey, "", ID_OB, -3, 0, {0}} }; /* PoseChannel KeyingSets ------ */ @@ -974,7 +974,7 @@ bKeyingSet defks_v3d_pchan[] = {NULL, "Rot", ID_PO, 0, 4, {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, {NULL, "Scale", ID_PO, 0, 3, {AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator {NULL, "LocRot", ID_PO, 0, 7, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W, @@ -992,7 +992,7 @@ bKeyingSet defks_v3d_pchan[] = {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z, AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator {NULL, "VisualLoc", ID_PO, INSERTKEY_MATRIX, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}}, {NULL, "VisualRot", ID_PO, INSERTKEY_MATRIX, 3, {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, @@ -1001,9 +1001,9 @@ bKeyingSet defks_v3d_pchan[] = {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W, AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator - {NULL, "Available", ID_PO, -2, 0, {}} + {NULL, "Available", ID_PO, -2, 0, {0}} }; /* Material KeyingSets ------ */ @@ -1017,7 +1017,7 @@ bKeyingSet defks_buts_shading_mat[] = {NULL, "Halo Size", ID_MA, 0, 1, {MA_HASIZE}}, {NULL, "Mode", ID_MA, 0, 1, {MA_MODE}}, // evil bitflags - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator {NULL, "All Color", ID_MA, 0, 18, {MA_COL_R,MA_COL_G,MA_COL_B, @@ -1030,7 +1030,7 @@ bKeyingSet defks_buts_shading_mat[] = {MA_RAYM,MA_FRESMIR,MA_FRESMIRI, MA_FRESTRA,MA_FRESTRAI}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator {NULL, "Ofs", ID_MA, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}}, {NULL, "Size", ID_MA, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}}, @@ -1041,9 +1041,9 @@ bKeyingSet defks_buts_shading_mat[] = MAP_R,MAP_G,MAP_B,MAP_DVAR, MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator - {NULL, "Available", ID_MA, -2, 0, {}} + {NULL, "Available", ID_MA, -2, 0, {0}} }; /* World KeyingSets ------ */ @@ -1055,13 +1055,13 @@ bKeyingSet defks_buts_shading_wo[] = {NULL, "Zenith RGB", ID_WO, 0, 3, {WO_ZEN_R,WO_ZEN_G,WO_ZEN_B}}, {NULL, "Horizon RGB", ID_WO, 0, 3, {WO_HOR_R,WO_HOR_G,WO_HOR_B}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator {NULL, "Mist", ID_WO, 0, 4, {WO_MISI,WO_MISTDI,WO_MISTSTA,WO_MISTHI}}, {NULL, "Stars", ID_WO, 0, 5, {WO_STAR_R,WO_STAR_G,WO_STAR_B,WO_STARDIST,WO_STARSIZE}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator {NULL, "Ofs", ID_WO, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}}, {NULL, "Size", ID_WO, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}}, @@ -1072,9 +1072,9 @@ bKeyingSet defks_buts_shading_wo[] = MAP_R,MAP_G,MAP_B,MAP_DVAR, MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator - {NULL, "Available", ID_WO, -2, 0, {}} + {NULL, "Available", ID_WO, -2, 0, {0}} }; /* Lamp KeyingSets ------ */ @@ -1087,7 +1087,7 @@ bKeyingSet defks_buts_shading_la[] = {NULL, "Energy", ID_LA, 0, 1, {LA_ENERGY}}, {NULL, "Spot Size", ID_LA, 0, 1, {LA_SPOTSI}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator {NULL, "Ofs", ID_LA, 0, 3, {MAP_OFS_X,MAP_OFS_Y,MAP_OFS_Z}}, {NULL, "Size", ID_LA, 0, 3, {MAP_SIZE_X,MAP_SIZE_Y,MAP_SIZE_Z}}, @@ -1098,9 +1098,9 @@ bKeyingSet defks_buts_shading_la[] = MAP_R,MAP_G,MAP_B,MAP_DVAR, MAP_COLF,MAP_NORF,MAP_VARF,MAP_DISP}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator - {NULL, "Available", ID_LA, -2, 0, {}} + {NULL, "Available", ID_LA, -2, 0, {0}} }; /* Texture KeyingSets ------ */ @@ -1144,9 +1144,9 @@ bKeyingSet defks_buts_shading_tex[] = {NULL, "Color Filter", ID_TE, 0, 5, {TE_COL_R,TE_COL_G,TE_COL_B,TE_BRIGHT,TE_CONTRA}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator - {NULL, "Available", ID_TE, -2, 0, {}} + {NULL, "Available", ID_TE, -2, 0, {0}} }; /* Object Buttons KeyingSets ------ */ @@ -1167,14 +1167,14 @@ bKeyingSet defks_buts_object[] = {incl_buts_ob, "Random Damping", ID_OB, 0, 1, {OB_PD_RDAMP}}, {incl_buts_ob, "Permeability", ID_OB, 0, 1, {OB_PD_PERM}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator {NULL, "Force Strength", ID_OB, 0, 1, {OB_PD_FSTR}}, {NULL, "Force Falloff", ID_OB, 0, 1, {OB_PD_FFALL}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator - {NULL, "Available", ID_OB, -2, 0, {}} // this will include ob-transforms too! + {NULL, "Available", ID_OB, -2, 0, {0}} // this will include ob-transforms too! }; /* Camera Buttons KeyingSets ------ */ @@ -1201,15 +1201,15 @@ bKeyingSet defks_buts_cam[] = {NULL, "Clipping", ID_CA, 0, 2, {CAM_STA,CAM_END}}, {NULL, "Focal Distance", ID_CA, 0, 1, {CAM_YF_FDIST}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator {incl_buts_cam2, "Aperture", ID_CA, 0, 1, {CAM_YF_APERT}}, {incl_buts_cam1, "Viewplane Shift", ID_CA, 0, 2, {CAM_SHIFT_X,CAM_SHIFT_Y}}, - {NULL, "%l", 0, -1, 0, {}}, // separator + {NULL, "%l", 0, -1, 0, {0}}, // separator - {NULL, "Available", ID_CA, -2, 0, {}} + {NULL, "Available", ID_CA, -2, 0, {0}} }; /* --- */ From 41a0b56b704758e1e024b2e0df6b97e17f700ecd Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Sun, 14 Sep 2008 19:34:06 +0000 Subject: [PATCH 068/125] BGE patch: new Physics button and margin parameter in Logic panel. Change subversion. The Physics button controls the creation of a physics representation of the object when starting the game. If the button is not selected, the object is a pure graphical object with no physics representation and all the other physics buttons are hidden. Selecting this button gives access to the usual physics buttons. The physics button is enabled by default to match previous Blender behavior. The margin parameter allows to control the collision margin from the UI. Previously, this parameter was only accessible through Python. By default, the collision margin is set to 0.0 on static objects and 0.06 on dynamic objects. To maintain compatibility with older games, the collision margin is set to 0.06 on all objects when loading older blend file. Note about the collision algorithms in Bullet 2.71 -------------------------------------------------- Bullet 2.71 handles the collision margin differently than Bullet 2.53 (the previous Bullet version in Blender). The collision margin is now kept "inside" the object for box, sphere and cylinder bound shapes. This means that two objects bound to any of these shape will come in close contact when colliding. The static mesh, convex hull and cone shapes still have their collision margin "outside" the object, which leaves a space of 1 or 2 times the collision margin between objects. The situation with Bullet 2.53 was more complicated, generally leading to more space between objects, except for box-box collisions. This means that running a old game under Bullet 2.71 may cause visual problems, especially if the objects are small. You can fix these problems by changing some visual aspect of the objects: center, shape, size, position of children, etc. --- source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/blenkernel/intern/object.c | 3 +- source/blender/blenloader/intern/readfile.c | 10 +- source/blender/makesdna/DNA_object_types.h | 6 +- source/blender/src/buttons_logic.c | 278 ++++++++++-------- .../Converter/BL_BlenderDataConversion.cpp | 5 + .../Ketsji/KX_ConvertPhysicsObject.h | 1 + .../Ketsji/KX_ConvertPhysicsObjects.cpp | 3 +- .../Physics/Bullet/CcdPhysicsController.cpp | 2 + .../Physics/Bullet/CcdPhysicsController.h | 2 + 10 files changed, 180 insertions(+), 132 deletions(-) diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index e403fc33e06..0591937ea4c 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 1 +#define BLENDER_SUBVERSION 2 #define BLENDER_MINVERSION 245 #define BLENDER_MINSUBVERSION 15 diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 3ed169ff77d..e63d6047cc6 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -960,7 +960,8 @@ Object *add_only_object(int type, char *name) ob->anisotropicFriction[0] = 1.0f; ob->anisotropicFriction[1] = 1.0f; ob->anisotropicFriction[2] = 1.0f; - ob->gameflag= OB_PROP; + ob->gameflag= OB_PROP|OB_PHYSICS; + ob->margin = 0.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 da85a264a0c..fc863ff2f5e 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7769,7 +7769,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) alphasort_version_246(fd, lib, me); } - if(main->versionfile <= 246 && main->subversionfile < 1){ + if(main->versionfile < 246 || (main->versionfile == 246 && main->subversionfile < 1)){ Object *ob; for(ob = main->object.first; ob; ob= ob->id.next) { if(ob->pd && (ob->pd->forcefield == PFIELD_WIND)) @@ -7777,6 +7777,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } + if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 2)){ + Object *ob; + for(ob = main->object.first; ob; ob= ob->id.next) { + ob->gameflag |= OB_PHYSICS; + ob->margin = 0.06; + } + } + /* 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_object_types.h b/source/blender/makesdna/DNA_object_types.h index d258cf77ef5..3708db3fd38 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -156,7 +156,9 @@ typedef struct Object { float formfactor; float rdamping, sizefac; - + float margin, pad3; + + char dt, dtx; char totcol; /* copy of mesh or curve or meta */ char actcol; /* currently selected material in the user interface */ @@ -427,6 +429,8 @@ extern Object workob; #define OB_PROP 16384 #define OB_MAINACTOR 32768 +#define OB_PHYSICS 65536 + /* ob->gameflag2 */ #define OB_NEVER_DO_ACTIVITY_CULLING 1 diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index a87104c82de..c2f2389a50f 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -2836,134 +2836,158 @@ void buttons_enji(uiBlock *block, Object *ob) void buttons_ketsji(uiBlock *block, Object *ob) { - uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", - 10,205,55,19, &ob->gameflag, 0, 0, 0, 0, - "Objects that are evaluated by the engine "); - if(ob->gameflag & OB_ACTOR) { - uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 65,205,55,19, - &ob->gameflag, 0, 0, 0, 0, - "Objects that don't restitute collisions (like a ghost)"); - uiDefButBitI(block, TOG, OB_DYNAMIC, B_REDR, "Dynamic", 120,205,70,19, - &ob->gameflag, 0, 0, 0, 0, - "Motion defined by laws of physics"); - - if(ob->gameflag & OB_DYNAMIC) { - uiDefButBitI(block, TOG, OB_RIGID_BODY, B_REDR, "Rigid Body", 190,205,80,19, - &ob->gameflag, 0, 0, 0, 0, - "Enable rolling physics"); - uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,205,80,19, - &ob->gameflag, 0, 0, 0, 0, - "Disable auto (de)activation"); - - uiDefButBitI(block, TOG, OB_DO_FH, B_DIFF, "Do Fh", 10,185,50,19, - &ob->gameflag, 0, 0, 0, 0, - "Use Fh settings in Materials"); - uiDefButBitI(block, TOG, OB_ROT_FH, B_DIFF, "Rot Fh", 60,185,50,19, - &ob->gameflag, 0, 0, 0, 0, - "Use face normal to rotate Object"); - uiDefButF(block, NUM, B_DIFF, "Mass:", 110, 185, 80, 19, - &ob->mass, 0.01, 10000.0, 10, 0, - "The mass of the Object"); - uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 190, 185, 80, 19, - &ob->inertia, 0.01, 10.0, 10, 0, - "Bounding sphere radius"); - uiDefButF(block, NUM, B_DIFF, "Form:", 270, 185, 80, 19, - &ob->formfactor, 0.01, 100.0, 10, 0, - "Form factor"); - - uiDefButF(block, NUM, B_DIFF, "Damp:", 10, 165, 100, 19, - &ob->damping, 0.0, 1.0, 10, 0, - "General movement damping"); - uiDefButF(block, NUM, B_DIFF, "RotDamp:", 110, 165, 120, 19, - &ob->rdamping, 0.0, 1.0, 10, 0, - "General rotation damping"); - uiDefButBitI(block, TOG, OB_ANISOTROPIC_FRICTION, B_REDR, "Anisotropic", - 230, 165, 120, 19, - &ob->gameflag, 0.0, 1.0, 10, 0, - "Enable anisotropic friction"); - } - - if (ob->gameflag & OB_ANISOTROPIC_FRICTION) { - uiDefButF(block, NUM, B_DIFF, "x friction:", 10, 145, 114, 19, - &ob->anisotropicFriction[0], 0.0, 1.0, 10, 0, - "Relative friction coefficient in the x-direction."); - uiDefButF(block, NUM, B_DIFF, "y friction:", 124, 145, 113, 19, - &ob->anisotropicFriction[1], 0.0, 1.0, 10, 0, - "Relative friction coefficient in the y-direction."); - uiDefButF(block, NUM, B_DIFF, "z friction:", 237, 145, 113, 19, - &ob->anisotropicFriction[2], 0.0, 1.0, 10, 0, - "Relative friction coefficient in the z-direction."); - } - } - - if (!(ob->gameflag & OB_GHOST)) { + uiDefButBitI(block, TOG, OB_PHYSICS, B_REDR, "Physics", + 10,205,70,19, &ob->gameflag, 0, 0, 0, 0, + "Objects that have a physics representation"); + if (ob->gameflag & OB_PHYSICS) { uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 10, 125, 75, 19, - &ob->gameflag, 0, 0,0, 0, - "Specify a bounds object for physics"); - if (ob->gameflag & OB_BOUNDS) { - uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull Polytope%x5|Static TriangleMesh %x4", - 85, 125, 160, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); - uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 250,125,100,19, - &ob->gameflag, 0, 0, 0, 0, - "Add Children"); + uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", + 80,205,55,19, &ob->gameflag, 0, 0, 0, 0, + "Objects that are evaluated by the engine "); + if(ob->gameflag & OB_ACTOR) { + uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 135,205,55,19, + &ob->gameflag, 0, 0, 0, 0, + "Objects that don't restitute collisions (like a ghost)"); + uiDefButBitI(block, TOG, OB_DYNAMIC, B_REDR, "Dynamic", 190,205,75,19, + &ob->gameflag, 0, 0, 0, 0, + "Motion defined by laws of physics"); + + if(ob->gameflag & OB_DYNAMIC) { + uiDefButBitI(block, TOG, OB_RIGID_BODY, B_REDR, "Rigid Body", 265,205,85,19, + &ob->gameflag, 0, 0, 0, 0, + "Enable rolling physics"); + + uiDefButF(block, NUM, B_DIFF, "Mass:", 10, 185, 130, 19, + &ob->mass, 0.01, 10000.0, 10, 2, + "The mass of the Object"); + uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 140, 185, 130, 19, + &ob->inertia, 0.01, 10.0, 10, 2, + "Bounding sphere radius"); + uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,185,80,19, + &ob->gameflag, 0, 0, 0, 0, + "Disable auto (de)activation"); + + uiDefButF(block, NUMSLI, B_DIFF, "Damp ", 10, 165, 150, 19, + &ob->damping, 0.0, 1.0, 10, 0, + "General movement damping"); + uiDefButF(block, NUMSLI, B_DIFF, "RotDamp ", 160, 165, 190, 19, + &ob->rdamping, 0.0, 1.0, 10, 0, + "General rotation damping"); + + uiDefButBitI(block, TOG, OB_DO_FH, B_DIFF, "Do Fh", 10,145,50,19, + &ob->gameflag, 0, 0, 0, 0, + "Use Fh settings in Materials"); + uiDefButBitI(block, TOG, OB_ROT_FH, B_DIFF, "Rot Fh", 60,145,50,19, + &ob->gameflag, 0, 0, 0, 0, + "Use face normal to rotate Object"); + uiDefButF(block, NUM, B_DIFF, "Form:", 110, 145, 120, 19, + &ob->formfactor, 0.01, 100.0, 10, 0, + "Form factor"); + + uiDefButBitI(block, TOG, OB_ANISOTROPIC_FRICTION, B_REDR, "Anisotropic", + 230, 145, 120, 19, + &ob->gameflag, 0.0, 1.0, 10, 0, + "Enable anisotropic friction"); + } + + if (ob->gameflag & OB_ANISOTROPIC_FRICTION) { + uiDefButF(block, NUM, B_DIFF, "x friction:", 10, 125, 114, 19, + &ob->anisotropicFriction[0], 0.0, 1.0, 10, 0, + "Relative friction coefficient in the x-direction."); + uiDefButF(block, NUM, B_DIFF, "y friction:", 124, 125, 113, 19, + &ob->anisotropicFriction[1], 0.0, 1.0, 10, 0, + "Relative friction coefficient in the y-direction."); + uiDefButF(block, NUM, B_DIFF, "z friction:", 237, 125, 113, 19, + &ob->anisotropicFriction[2], 0.0, 1.0, 10, 0, + "Relative friction coefficient in the z-direction."); + } + } + + if (!(ob->gameflag & OB_GHOST)) { + 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"); + 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", + 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, + "Add Children"); + } + uiBlockEndAlign(block); } - uiBlockEndAlign(block); } } void buttons_bullet(uiBlock *block, Object *ob) { - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", - 10,205,55,19, &ob->gameflag, 0, 0, 0, 0, - "Objects that are evaluated by the engine "); - if(ob->gameflag & OB_ACTOR) { - uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 65,205,55,19, - &ob->gameflag, 0, 0, 0, 0, - "Objects that don't restitute collisions (like a ghost)"); - uiDefButBitI(block, TOG, OB_DYNAMIC, B_REDR, "Dynamic", 120,205,70,19, - &ob->gameflag, 0, 0, 0, 0, - "Motion defined by laws of physics"); - - if(ob->gameflag & OB_DYNAMIC) { - uiDefButBitI(block, TOG, OB_RIGID_BODY, B_REDR, "Rigid Body", 190,205,80,19, - &ob->gameflag, 0, 0, 0, 0, - "Enable rolling physics"); - uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,205,80,19, - &ob->gameflag, 0, 0, 0, 0, - "Disable auto (de)activation"); + uiDefButBitI(block, TOG, OB_PHYSICS, B_REDR, "Physics", + 10,205,70,19, &ob->gameflag, 0, 0, 0, 0, + "Objects that have a physics representation"); + if (ob->gameflag & OB_PHYSICS) { + uiBlockBeginAlign(block); + uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", + 80,205,55,19, &ob->gameflag, 0, 0, 0, 0, + "Objects that are detected by the Near and Radar sensor"); + if(ob->gameflag & OB_ACTOR) { + uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 135,205,55,19, + &ob->gameflag, 0, 0, 0, 0, + "Objects that don't restitute collisions (like a ghost)"); + uiDefButBitI(block, TOG, OB_DYNAMIC, B_REDR, "Dynamic", 190,205,75,19, + &ob->gameflag, 0, 0, 0, 0, + "Motion defined by laws of physics"); + + if(ob->gameflag & OB_DYNAMIC) { + uiDefButBitI(block, TOG, OB_RIGID_BODY, B_REDR, "Rigid Body", 265,205,85,19, + &ob->gameflag, 0, 0, 0, 0, + "Enable rolling physics"); - uiDefButF(block, NUM, B_DIFF, "Mass:", 10, 185, 170, 19, - &ob->mass, 0.01, 10000.0, 10, 2, - "The mass of the Object"); - uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 180, 185, 170, 19, - &ob->inertia, 0.01, 10.0, 10, 2, - "Bounding sphere radius"); + uiDefButF(block, NUM, B_DIFF, "Mass:", 10, 185, 130, 19, + &ob->mass, 0.01, 10000.0, 10, 2, + "The mass of the Object"); + uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 140, 185, 130, 19, + &ob->inertia, 0.01, 10.0, 10, 2, + "Bounding sphere radius, not used for other bounding shapes"); + uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,185,80,19, + &ob->gameflag, 0, 0, 0, 0, + "Disable auto (de)activation"); - uiDefButF(block, NUMSLI, B_DIFF, "Damp ", 10, 165, 150, 19, - &ob->damping, 0.0, 1.0, 10, 0, - "General movement damping"); - uiDefButF(block, NUMSLI, B_DIFF, "RotDamp ", 160, 165, 190, 19, - &ob->rdamping, 0.0, 1.0, 10, 0, - "General rotation damping"); + uiDefButF(block, NUMSLI, B_DIFF, "Damp ", 10, 165, 150, 19, + &ob->damping, 0.0, 1.0, 10, 0, + "General movement damping"); + uiDefButF(block, NUMSLI, B_DIFF, "RotDamp ", 160, 165, 190, 19, + &ob->rdamping, 0.0, 1.0, 10, 0, + "General rotation damping"); + } } - } - uiBlockEndAlign(block); + uiBlockEndAlign(block); - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 10, 125, 75, 19, - &ob->gameflag, 0, 0,0, 0, - "Specify a bounds object for physics"); - if (ob->gameflag & OB_BOUNDS) { - uiDefButS(block, MENU, REDRAWVIEW3D, "Boundary Display%t|Box%x0|Sphere%x1|Cylinder%x2|Cone%x3|Convex Hull Polytope%x5|Static TriangleMesh %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|", - 85, 125, 160, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); - uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 250,125,100,19, - &ob->gameflag, 0, 0, 0, 0, - "Add Children"); + uiBlockBeginAlign(block); + if ((ob->gameflag & (OB_ACTOR|OB_DYNAMIC)) == (OB_ACTOR|OB_DYNAMIC)) { + if (ob->margin < 0.001f) + ob->margin = 0.06f; + uiDefButF(block, NUM, B_DIFF, "Margin", 10, 105, 105, 19, + &ob->margin, 0.001, 1.0, 1, 0, + "Collision margin"); + } else { + uiDefButF(block, NUM, B_DIFF, "Margin", 10, 105, 105, 19, + &ob->margin, 0.0, 1.0, 1, 0, + "Collision margin"); + } + uiDefButBitI(block, TOG, OB_BOUNDS, B_REDR, "Bounds", 115, 105, 55, 19, + &ob->gameflag, 0, 0,0, 0, + "Specify a bounds object for physics"); + 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", + //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|", + 170, 105, 105, 19, &ob->boundtype, 0, 0, 0, 0, "Selects the collision type"); + uiDefButBitI(block, TOG, OB_CHILD, B_REDR, "Compound", 275,105,75,19, + &ob->gameflag, 0, 0, 0, 0, + "Add Children"); + } + uiBlockEndAlign(block); } - uiBlockEndAlign(block); } static void check_object_state(void *arg1_but, void *arg2_mask) @@ -3132,7 +3156,7 @@ void logic_buts(void) uiBlockSetCol(block, TH_AUTO); uiBlockBeginAlign(block); - uiDefBut(block, BUT, B_ADD_PROP, "Add Property", 10, 90, 340, 24, + uiDefBut(block, BUT, B_ADD_PROP, "Add Property", 10, 70, 340, 24, NULL, 0.0, 100.0, 100, 0, ""); @@ -3141,26 +3165,26 @@ void logic_buts(void) a= 0; prop= ob->prop.first; while(prop) { - but= uiDefBut(block, BUT, 1, "Del", 10, (short)(70-20*a), 40, 20, NULL, 0.0, 0.0, 1, (float)a, ""); + but= uiDefBut(block, BUT, 1, "Del", 10, (short)(50-20*a), 40, 20, NULL, 0.0, 0.0, 1, (float)a, ""); uiButSetFunc(but, del_property, prop, NULL); - uiDefButS(block, MENU, B_CHANGE_PROP, pupstr, 50, (short)(70-20*a), 60, 20, &prop->type, 0, 0, 0, 0, ""); - but= uiDefBut(block, TEX, 1, "Name:", 110, (short)(70-20*a), 110, 20, prop->name, 0, 31, 0, 0, ""); + uiDefButS(block, MENU, B_CHANGE_PROP, pupstr, 50, (short)(50-20*a), 60, 20, &prop->type, 0, 0, 0, 0, ""); + but= uiDefBut(block, TEX, 1, "Name:", 110, (short)(50-20*a), 110, 20, prop->name, 0, 31, 0, 0, ""); uiButSetFunc(but, make_unique_prop_names_cb, prop->name, (void*) 1); if(prop->type==PROP_BOOL) { - uiDefButBitI(block, TOG, 1, B_REDR, "True", 220, (short)(70-20*a), 55, 20, &prop->data, 0, 0, 0, 0, ""); - uiDefButBitI(block, TOGN, 1, B_REDR, "False", 270, (short)(70-20*a), 55, 20, &prop->data, 0, 0, 0, 0, ""); + uiDefButBitI(block, TOG, 1, B_REDR, "True", 220, (short)(50-20*a), 55, 20, &prop->data, 0, 0, 0, 0, ""); + uiDefButBitI(block, TOGN, 1, B_REDR, "False", 270, (short)(50-20*a), 55, 20, &prop->data, 0, 0, 0, 0, ""); } else if(prop->type==PROP_INT) - uiDefButI(block, NUM, B_REDR, "", 220, (short)(70-20*a), 110, 20, &prop->data, -10000, 10000, 0, 0, ""); + uiDefButI(block, NUM, B_REDR, "", 220, (short)(50-20*a), 110, 20, &prop->data, -10000, 10000, 0, 0, ""); else if(prop->type==PROP_FLOAT) - uiDefButF(block, NUM, B_REDR, "", 220, (short)(70-20*a), 110, 20, (float*) &prop->data, -10000, 10000, 100, 3, ""); + uiDefButF(block, NUM, B_REDR, "", 220, (short)(50-20*a), 110, 20, (float*) &prop->data, -10000, 10000, 100, 3, ""); else if(prop->type==PROP_STRING) - uiDefBut(block, TEX, B_REDR, "", 220, (short)(70-20*a), 110, 20, prop->poin, 0, 127, 0, 0, ""); + uiDefBut(block, TEX, B_REDR, "", 220, (short)(50-20*a), 110, 20, prop->poin, 0, 127, 0, 0, ""); else if(prop->type==PROP_TIME) - uiDefButF(block, NUM, B_REDR, "", 220, (short)(70-20*a), 110, 20, (float*) &prop->data, -10000, 10000, 100, 3, ""); + uiDefButF(block, NUM, B_REDR, "", 220, (short)(50-20*a), 110, 20, (float*) &prop->data, -10000, 10000, 100, 3, ""); - uiDefButBitS(block, TOG, PROP_DEBUG, B_REDR, "D", 330, (short)(70-20*a), 20, 20, &prop->flag, 0, 0, 0, 0, "Print Debug info"); + uiDefButBitS(block, TOG, PROP_DEBUG, B_REDR, "D", 330, (short)(50-20*a), 20, 20, &prop->flag, 0, 0, 0, 0, "Print Debug info"); a++; prop= prop->next; diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 19fb9d01cbf..8bdec219354 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1279,6 +1279,10 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, //int userigidbody = SYS_GetCommandLineInt(syshandle,"norigidbody",0); //bool bRigidBody = (userigidbody == 0); + // object has physics representation? + if (!(blenderobject->gameflag & OB_PHYSICS)) + return; + // get Root Parent of blenderobject struct Object* parent= blenderobject->parent; while(parent && parent->parent) { @@ -1310,6 +1314,7 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, objprop.m_isCompoundChild = isCompoundChild; objprop.m_hasCompoundChildren = (blenderobject->gameflag & OB_CHILD) != 0; + objprop.m_margin = blenderobject->margin; if ((objprop.m_isactor = (blenderobject->gameflag & OB_ACTOR)!=0)) { diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h index 6653026f28a..248d2f49b0b 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h @@ -86,6 +86,7 @@ struct KX_ObjectProperties bool m_disableSleeping; bool m_hasCompoundChildren; bool m_isCompoundChild; + double m_margin; KX_BoundBoxClass m_boundclass; union { KX_BoxBounds box; diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 6507bf501e4..b3f24d97281 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -699,6 +699,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, ci.m_gravity = btVector3(0,0,0); ci.m_localInertiaTensor =btVector3(0,0,0); ci.m_mass = objprop->m_dyna ? shapeprops->m_mass : 0.f; + ci.m_margin = objprop->m_margin; shapeInfo->m_radius = objprop->m_radius; isbulletdyna = objprop->m_dyna; @@ -786,7 +787,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, return; } - bm->setMargin(0.06); + bm->setMargin(ci.m_margin); if (objprop->m_isCompoundChild) diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 4da9143fc3d..8ba138df437 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -277,7 +277,9 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta if (m_collisionShape) { // new shape has no scaling, apply initial scaling + m_collisionShape->setMargin(m_cci.m_margin); m_collisionShape->setLocalScaling(m_cci.m_scaling); + if (m_cci.m_mass) m_collisionShape->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor); } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index a685c466944..7d55851ebf6 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -145,6 +145,7 @@ struct CcdConstructionInfo m_friction(0.5f), m_linearDamping(0.1f), m_angularDamping(0.1f), + m_margin(0.06f), m_collisionFlags(0), m_bRigid(false), m_collisionFilterGroup(DefaultFilter), @@ -165,6 +166,7 @@ struct CcdConstructionInfo btScalar m_friction; btScalar m_linearDamping; btScalar m_angularDamping; + btScalar m_margin; int m_collisionFlags; bool m_bRigid; From f554f14329cb6c69dfbaf97f055d4651726aa8a3 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 14 Sep 2008 21:31:07 +0000 Subject: [PATCH 069/125] Fix for bug #17617: GLSL shaders change vertex color unexpectedly. --- source/gameengine/Rasterizer/RAS_MaterialBucket.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index 69a8271d3e8..788af29c4bb 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -560,7 +560,7 @@ void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRa if (m_material->GetDrawingMode() & RAS_IRasterizer::RAS_RENDER_3DPOLYGON_TEXT) rasty->IndexPrimitives_3DText(ms, m_material, rendertools); // for multitexturing - else if((m_material->GetFlag() & RAS_MULTITEX)) + else if((m_material->GetFlag() & (RAS_MULTITEX|RAS_BLENDERGLSL))) rasty->IndexPrimitivesMulti(ms); // use normal IndexPrimitives else From 3b153f887a507181ec37d11eb4ba98dd778f216c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 15 Sep 2008 00:11:30 +0000 Subject: [PATCH 070/125] Fix zoom level and clipping to be consistent with the viewport when pressing P without a camera active, now it should match the view exactly. Fix an issue when setting a camera with an actuator and being in orthographic mode in the viewport without an active camera, it used a strange mix of the set camera and the viewport then. --- .../BlenderRoutines/BL_KetsjiEmbedStart.cpp | 11 +++++++-- source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 24 +++++++++++++++---- source/gameengine/Ketsji/KX_KetsjiEngine.h | 3 +++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index fa771cb3ce8..74fe6c68863 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -198,6 +198,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, // some blender stuff MT_CmMatrix4x4 projmat; MT_CmMatrix4x4 viewmat; + float camzoom; int i; for (i = 0; i < 16; i++) @@ -211,8 +212,13 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, projmat.setElem(i, projmat_linear[i]); } - float camzoom = (1.41421 + (v3d->camzoom / 50.0)); - camzoom *= camzoom; + if(v3d->persp==V3D_CAMOB) { + camzoom = (1.41421 + (v3d->camzoom / 50.0)); + camzoom *= camzoom; + } + else + camzoom = 2.0; + camzoom = 4.0 / camzoom; ketsjiengine->SetDrawType(v3d->drawtype); @@ -293,6 +299,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, ketsjiengine->SetCameraOverrideUseOrtho((v3d->persp == V3D_ORTHO)); ketsjiengine->SetCameraOverrideProjectionMatrix(projmat); ketsjiengine->SetCameraOverrideViewMatrix(viewmat); + ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far); } // create a scene converter, create and convert the startingscene diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 4d83853537e..888dcf3d01f 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -135,6 +135,8 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) m_overrideCam(false), m_overrideCamUseOrtho(false), + m_overrideCamNear(0.0), + m_overrideCamFar(0.0), m_stereo(false), m_curreye(0), @@ -886,7 +888,12 @@ void KX_KetsjiEngine::SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat) m_overrideCamViewMat = mat; } - +void KX_KetsjiEngine::SetCameraOverrideClipping(float near, float far) +{ + m_overrideCamNear = near; + m_overrideCamFar = far; +} + void KX_KetsjiEngine::SetupViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport) { // In this function we make sure the rasterizer settings are upto @@ -985,6 +992,7 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) // update graphics void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) { + bool override_camera; RAS_Rect viewport, area; float left, right, bottom, top, nearfrust, farfrust, focallength; const float ortho = 100.0; @@ -1006,7 +1014,10 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) //m_rasterizer->SetAmbient(); m_rasterizer->DisplayFog(); - if (m_overrideCam && (scene->GetName() == m_overrideSceneName) && m_overrideCamUseOrtho) { + override_camera = m_overrideCam && (scene->GetName() == m_overrideSceneName); + override_camera = override_camera && (cam->GetName() == "__default__cam__"); + + if (override_camera && m_overrideCamUseOrtho) { MT_CmMatrix4x4 projmat = m_overrideCamProjMat; m_rasterizer->SetProjectionMatrix(projmat); } else if (cam->hasValidProjectionMatrix() && !cam->GetViewport() ) @@ -1016,12 +1027,17 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) { RAS_FrameFrustum frustum; float lens = cam->GetLens(); + bool orthographic = !cam->GetCameraData()->m_perspective; nearfrust = cam->GetCameraNear(); farfrust = cam->GetCameraFar(); focallength = cam->GetFocalLength(); - if (!cam->GetCameraData()->m_perspective) - { + if(override_camera) { + nearfrust = m_overrideCamNear; + farfrust = m_overrideCamFar; + } + + if (orthographic) { lens *= ortho; nearfrust = (nearfrust + 1.0)*ortho; farfrust *= ortho; diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 89f6fe55045..8fe8731dc05 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -124,6 +124,8 @@ private: bool m_overrideCamUseOrtho; MT_CmMatrix4x4 m_overrideCamProjMat; MT_CmMatrix4x4 m_overrideCamViewMat; + float m_overrideCamNear; + float m_overrideCamFar; bool m_stereo; int m_curreye; @@ -236,6 +238,7 @@ public: void SetCameraOverrideUseOrtho(bool useOrtho); void SetCameraOverrideProjectionMatrix(const MT_CmMatrix4x4& mat); void SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat); + void SetCameraOverrideClipping(float near, float far); /** * Sets display of all frames. From a24960daa8c4555e13bd0218cd735df4063b0e57 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 15 Sep 2008 00:34:43 +0000 Subject: [PATCH 071/125] Fix for bug #4859: once a visibility actuator was set it was not possible to change the visibility again through python for example. This is because the actuator kept setting the visibility again each frame, as a workaround for there being no separate visible and viewport culling flag, but that was added some time ago. --- source/gameengine/Ketsji/KX_VisibilityActuator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp index 60ea6ace53b..e60a8d7c099 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp @@ -80,7 +80,7 @@ KX_VisibilityActuator::Update() obj->SetVisible(m_visible, m_recursive); obj->UpdateBuckets(m_recursive); - return true; + return false; } /* ------------------------------------------------------------------------- */ From 2c31cc4503ee4de8e8c4ff5665ed1e7dbabfb832 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 15 Sep 2008 00:57:11 +0000 Subject: [PATCH 072/125] Fix for bug #17620: the motion blur actuator did not work correct with an always sensor, it kept resettting the motion blur each frame. --- source/gameengine/GameLogic/SCA_2DFilterActuator.cpp | 8 +++----- .../RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp | 5 ++++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp index 96a770a553f..9ec4ea00337 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp @@ -23,8 +23,8 @@ SCA_2DFilterActuator::SCA_2DFilterActuator( : SCA_IActuator(gameobj, T), m_type(type), m_flag(flag), - m_int_arg(int_arg), m_float_arg(float_arg), + m_int_arg(int_arg), m_rasterizer(rasterizer), m_rendertools(rendertools) { @@ -64,13 +64,11 @@ bool SCA_2DFilterActuator::Update() if( m_type == RAS_2DFilterManager::RAS_2DFILTER_MOTIONBLUR ) { if(!m_flag) - { m_rasterizer->EnableMotionBlur(m_float_arg); - } else - { m_rasterizer->DisableMotionBlur(); - } + + return false; } else if(m_type < RAS_2DFilterManager::RAS_2DFILTER_NUMBER_OF_FILTERS) { diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 4f31ae7fcbc..87a0a1d8b9e 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -949,7 +949,10 @@ void RAS_OpenGLRasterizer::SetPolygonOffset(float mult, float add) void RAS_OpenGLRasterizer::EnableMotionBlur(float motionblurvalue) { - m_motionblur = 1; + /* don't just set m_motionblur to 1, but check if it is 0 so + * we don't reset a motion blur that is already enabled */ + if(m_motionblur == 0) + m_motionblur = 1; m_motionblurvalue = motionblurvalue; } From ac86c04401686a9d119ea84ad489ca3db7403e5c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 15 Sep 2008 01:32:53 +0000 Subject: [PATCH 073/125] added BLI_convertstringcwd, used so command line blendfiles and python scripts can be relative to the current path. - was alredy doing this for blendfiles, but better to have in its own function. header_text.c - renamed PATH_MAX, was defined by system includes. --- source/blender/blenlib/BLI_blenlib.h | 1 + source/blender/blenlib/intern/util.c | 43 +++++++++++++++++++++++++++ source/blender/python/BPY_extern.h | 2 +- source/blender/python/BPY_interface.c | 34 +++++++++++++-------- source/blender/src/header_text.c | 8 ++--- source/creator/creator.c | 36 +--------------------- 6 files changed, 71 insertions(+), 53 deletions(-) diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index c59cd2dab4e..a1db7adf33d 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -151,6 +151,7 @@ void BLI_cleanup_dir(const char *relabase, char *dir); /* same as above but adds */ int BLI_convertstringcode(char *path, const char *basepath); int BLI_convertstringframe(char *path, int frame); +int BLI_convertstringcwd(char *path); void BLI_makestringcode(const char *relfile, char *file); diff --git a/source/blender/blenlib/intern/util.c b/source/blender/blenlib/intern/util.c index a31121148e3..c27efcb7934 100644 --- a/source/blender/blenlib/intern/util.c +++ b/source/blender/blenlib/intern/util.c @@ -1211,6 +1211,49 @@ int BLI_convertstringcode(char *path, const char *basepath) return wasrelative; } + +/* + * Should only be done with command line paths. + * this is NOT somthing blenders internal paths support like the // prefix + */ +int BLI_convertstringcwd(char *path) +{ + int wasrelative = 1; + int filelen = strlen(path); + +#ifdef WIN32 + if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/')) + wasrelative = 0; +#else + if (filelen >= 2 && path[0] == '/') + wasrelative = 0; +#endif + + if (wasrelative==1) { + char cwd[FILE_MAXDIR + FILE_MAXFILE]; + BLI_getwdN(cwd); /* incase the full path to the blend isnt used */ + + if (cwd[0] == '\0') { + printf( "Could not get the current working directory - $PWD for an unknown reason."); + } else { + /* uses the blend path relative to cwd important for loading relative linked files. + * + * cwd should contain c:\ etc on win32 so the relbase can be NULL + * relbase being NULL also prevents // being misunderstood as relative to the current + * blend file which isnt a feature we want to use in this case since were dealing + * with a path from the command line, rather then from inside Blender */ + + char origpath[FILE_MAXDIR + FILE_MAXFILE]; + BLI_strncpy(origpath, path, FILE_MAXDIR + FILE_MAXFILE); + + BLI_make_file_string(NULL, path, cwd, origpath); + } + } + + return wasrelative; +} + + /* copy di to fi, filename only */ void BLI_splitdirstring(char *di, char *fi) { diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index 3d9b45051fb..4b96ef3fdf0 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -94,7 +94,7 @@ extern "C" { int BPY_menu_do_python( short menutype, int event ); int BPY_menu_do_shortcut( short menutype, unsigned short key, unsigned short modifiers ); int BPY_menu_invoke( struct BPyMenu *pym, short menutype ); - void BPY_run_python_script( char *filename ); + void BPY_run_python_script( const char *filename ); int BPY_run_script(struct Script *script); void BPY_free_compiled_text( struct Text *text ); diff --git a/source/blender/python/BPY_interface.c b/source/blender/python/BPY_interface.c index c91aabc4a02..041ba069928 100644 --- a/source/blender/python/BPY_interface.c +++ b/source/blender/python/BPY_interface.c @@ -720,13 +720,23 @@ int BPY_txt_do_python_Text( struct Text *text ) * automatically. The script can be a file or a Blender Text in the current * .blend. ****************************************************************************/ -void BPY_run_python_script( char *fn ) +void BPY_run_python_script( const char *fn ) { + char filename[FILE_MAXDIR + FILE_MAXFILE]; Text *text = NULL; int is_blender_text = 0; - - if (!BLI_exists(fn)) { /* if there's no such filename ... */ - text = G.main->text.first; /* try an already existing Blender Text */ + + BLI_strncpy(filename, fn, FILE_MAXDIR + FILE_MAXFILE); + + if (!BLI_exists(filename)) + BLI_convertstringcwd(filename); + + if (!BLI_exists(filename)) { /* if there's no such filename ... */ + /* try an already existing Blender Text. + * use 'fn' rather then filename for this since were looking for + * internal text + */ + text = G.main->text.first; while (text) { if (!strcmp(fn, text->id.name + 2)) break; @@ -741,11 +751,14 @@ void BPY_run_python_script( char *fn ) } else { - text = add_text(fn); + /* use filename here since we know it exists, + * 'fn' may have been a relative path + */ + text = add_text(filename); if (text == NULL) { printf("\nError in BPY_run_python_script:\n" - "couldn't create Blender text from %s\n", fn); + "couldn't create Blender text from \"%s\"\n", filename); /* Chris: On Windows if I continue I just get a segmentation * violation. To get a baseline file I exit here. */ exit(2); @@ -762,13 +775,8 @@ void BPY_run_python_script( char *fn ) /* We can't simply free the text, since the script might have called * Blender.Load() to load a new .blend, freeing previous data. * So we check if the pointer is still valid. */ - Text *txtptr = G.main->text.first; - while (txtptr) { - if (txtptr == text) { - free_libblock(&G.main->text, text); - break; - } - txtptr = txtptr->id.next; + if (BLI_findindex(&G.main->text, text) != -1) { + free_libblock(&G.main->text, text); } } } diff --git a/source/blender/src/header_text.c b/source/blender/src/header_text.c index e7552434b19..eeea43ec57a 100644 --- a/source/blender/src/header_text.c +++ b/source/blender/src/header_text.c @@ -862,14 +862,14 @@ static uiBlock *text_filemenu(void *arg_unused) } /* header */ -#define PATH_MAX 260 +#define HEADER_PATH_MAX 260 void text_buttons(void) { uiBlock *block; SpaceText *st= curarea->spacedata.first; Text *text; short xco, xmax; - char naam[256], fname[PATH_MAX], headtxt[PATH_MAX+17]; + char naam[256], fname[HEADER_PATH_MAX], headtxt[HEADER_PATH_MAX+17]; int len; if (st==NULL || st->spacetype != SPACE_TEXT) return; @@ -961,8 +961,8 @@ void text_buttons(void) if (text) { if (text->name) { len = strlen(text->name); - if (len > PATH_MAX-1) - len = PATH_MAX-1; + if (len > HEADER_PATH_MAX-1) + len = HEADER_PATH_MAX-1; strncpy(fname, text->name, len); fname[len]='\0'; if (text->flags & TXT_ISDIRTY) diff --git a/source/creator/creator.c b/source/creator/creator.c index ec87cdd8cf7..bdd16dc6bed 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -772,44 +772,10 @@ int main(int argc, char **argv) else { /* Make the path absolute because its needed for relative linked blends to be found */ - int abs = 0; - int filelen; - char cwd[FILE_MAXDIR + FILE_MAXFILE]; char filename[FILE_MAXDIR + FILE_MAXFILE]; - cwd[0] = filename[0] = '\0'; BLI_strncpy(filename, argv[a], sizeof(filename)); - filelen = strlen(filename); - - /* relative path checks, could do more tests here... */ -#ifdef WIN32 - /* Account for X:/ and X:\ - should be enough */ - if (filelen >= 3 && filename[1] == ':' && (filename[2] == '\\' || filename[2] == '/')) - abs = 1; -#else - if (filelen >= 2 && filename[0] == '/') - abs = 1 ; -#endif - if (!abs) { - BLI_getwdN(cwd); /* incase the full path to the blend isnt used */ - - if (cwd[0] == '\0') { - printf( - "Could not get the current working directory - $PWD for an unknown reason.\n\t" - "Relative linked files will not load if the entire blend path is not used.\n\t" - "The 'Play' button may also fail.\n" - ); - } else { - /* uses the blend path relative to cwd important for loading relative linked files. - * - * cwd should contain c:\ etc on win32 so the relbase can be NULL - * relbase being NULL also prevents // being misunderstood as relative to the current - * blend file which isnt a feature we want to use in this case since were dealing - * with a path from the command line, rather then from inside Blender */ - - BLI_make_file_string(NULL, filename, cwd, argv[a]); - } - } + BLI_convertstringcwd(filename); if (G.background) { int retval = BKE_read_file(filename, NULL); From 89721ec4de25172a7ae725eb0a7334ecd5a96535 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 15 Sep 2008 02:18:37 +0000 Subject: [PATCH 074/125] replaced static make_absolute_filename with BLI_convertstringcwd --- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 47 +------------------ 1 file changed, 1 insertion(+), 46 deletions(-) diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index a50577e2266..c4e738c1896 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -199,51 +199,6 @@ void usage(char* program) printf("example: %s -g show_framerate = 0 c:\\loadtest.blend\n", program); } -static void make_absolute_filename(char *blendfilename) -{ - int abs = 0; - int filelen; - char cwd[FILE_MAXDIR + FILE_MAXFILE]; - char filename[FILE_MAXDIR + FILE_MAXFILE]; - - cwd[0] = filename[0] = '\0'; - - BLI_strncpy(filename, blendfilename, sizeof(filename)); - filelen = strlen(filename); - - /* relative path checks, could do more tests here... */ -#ifdef WIN32 - /* Account for X:/ and X:\ - should be enough */ - if (filelen >= 3 && filename[1] == ':' && (filename[2] == '\\' || filename[2] == '/')) - abs = 1; -#else - if (filelen >= 2 && filename[0] == '/') - abs = 1 ; -#endif - if (!abs) { - BLI_getwdN(cwd); /* incase the full path to the blend isnt used */ - - if (cwd[0] == '\0') { - printf( - "Could not get the current working directory - $PWD for an unknown reason.\n\t" - "Relative linked files will not load if the entire blend path is not used.\n\t" - "The 'Play' button may also fail.\n" - ); - } else { - /* uses the blend path relative to cwd important for loading relative linked files. - * - * cwd should contain c:\ etc on win32 so the relbase can be NULL - * relbase being NULL also prevents // being misunderstood as relative to the current - * blend file which isnt a feature we want to use in this case since were dealing - * with a path from the command line, rather then from inside Blender */ - - BLI_make_file_string(NULL, filename, cwd, blendfilename); - } - } - - BLI_strncpy(blendfilename, filename, sizeof(filename)); -} - static void get_filename(int argc, char **argv, char *filename) { #ifdef __APPLE__ @@ -633,7 +588,7 @@ int main(int argc, char** argv) get_filename(argc, argv, filename); if(filename[0]) - make_absolute_filename(filename); + BLI_convertstringcwd(filename); do { From ec30a3a470ef9e5cff0d71ef753767d5c1c2402f Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Mon, 15 Sep 2008 04:15:37 +0000 Subject: [PATCH 075/125] Delete Key Tool - Bugfixes: * Available option would crash * 'Visual' options are now not available for this tool (are not relevant) --- source/blender/src/keyframing.c | 36 ++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/source/blender/src/keyframing.c b/source/blender/src/keyframing.c index 19918a70a33..8f887cd4756 100644 --- a/source/blender/src/keyframing.c +++ b/source/blender/src/keyframing.c @@ -886,6 +886,19 @@ short deletekey (ID *id, int blocktype, char *actname, char *constname, int adrc /* --- */ +/* check if option not available for deleting keys */ +static short incl_non_del_keys (bKeyingSet *ks, const char mode[]) +{ + /* as optimisation, assume that it is sufficient to check only first letter + * of mode (int comparison should be faster than string!) + */ + //if (strcmp(mode, "Delete")==0) + if (mode && mode[0]=='D') + return 0; + + return 1; +} + /* Object KeyingSets ------ */ /* check if include shapekey entry */ @@ -946,12 +959,12 @@ bKeyingSet defks_v3d_object[] = {OB_ROT_X,OB_ROT_Y,OB_ROT_Z, OB_SIZE_X,OB_SIZE_Y,OB_SIZE_Z}}, - {NULL, "%l", 0, -1, 0, {0}}, // separator + {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator - {NULL, "VisualLoc", ID_OB, INSERTKEY_MATRIX, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}}, - {NULL, "VisualRot", ID_OB, INSERTKEY_MATRIX, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, + {incl_non_del_keys, "VisualLoc", ID_OB, INSERTKEY_MATRIX, 3, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z}}, + {incl_non_del_keys, "VisualRot", ID_OB, INSERTKEY_MATRIX, 3, {OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, - {NULL, "VisualLocRot", ID_OB, INSERTKEY_MATRIX, 6, + {incl_non_del_keys, "VisualLocRot", ID_OB, INSERTKEY_MATRIX, 6, {OB_LOC_X,OB_LOC_Y,OB_LOC_Z, OB_ROT_X,OB_ROT_Y,OB_ROT_Z}}, @@ -992,12 +1005,12 @@ bKeyingSet defks_v3d_pchan[] = {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z, AC_SIZE_X,AC_SIZE_Y,AC_SIZE_Z}}, - {NULL, "%l", 0, -1, 0, {0}}, // separator + {incl_non_del_keys, "%l", 0, -1, 0, {0}}, // separator - {NULL, "VisualLoc", ID_PO, INSERTKEY_MATRIX, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}}, - {NULL, "VisualRot", ID_PO, INSERTKEY_MATRIX, 3, {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, + {incl_non_del_keys, "VisualLoc", ID_PO, INSERTKEY_MATRIX, 3, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z}}, + {incl_non_del_keys, "VisualRot", ID_PO, INSERTKEY_MATRIX, 3, {AC_QUAT_W,AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, - {NULL, "VisualLocRot", ID_PO, INSERTKEY_MATRIX, 7, + {incl_non_del_keys, "VisualLocRot", ID_PO, INSERTKEY_MATRIX, 7, {AC_LOC_X,AC_LOC_Y,AC_LOC_Z,AC_QUAT_W, AC_QUAT_X,AC_QUAT_Y,AC_QUAT_Z}}, @@ -1689,7 +1702,7 @@ void common_modifykey (short mode) /* special hacks for 'available' option */ if (ks->flag == -2) { - IpoCurve *icu= NULL; + IpoCurve *icu= NULL, *icn= NULL; /* get first IPO-curve */ if (cks->act && cks->actname) { @@ -1703,9 +1716,12 @@ void common_modifykey (short mode) icu= cks->ipo->curve.first; /* we get adrcodes directly from IPO curves (see method below...) */ - for (; icu; icu= icu->next) { + for (; icu; icu= icn) { short flag; + /* get next ipo-curve in case current is deleted */ + icn= icu->next; + /* insert mode or delete mode */ if (mode == COMMONKEY_MODE_DELETE) { /* local flags only add on to global flags */ From a08b21263e1b38481aa09289275ab8706cff82b4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 15 Sep 2008 09:08:36 +0000 Subject: [PATCH 076/125] tooltip improvements from dfelinto, some minor edits --- source/blender/src/buttons_logic.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index c2f2389a50f..d75eaeb2fbb 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -1054,10 +1054,10 @@ static void draw_default_sensor_header(bSensor *sens, (short)(x + 10 + 0.85 * (w-20)), (short)(y - 19), (short)(0.15 * (w-20)), 19, &sens->invert, 0.0, 0.0, 0, 0, "Invert the level (output) of this sensor"); - uiDefButS(block, TOG, 1, "Lvl", - (short)(x + 10 + 0.70 * (w-20)), (short)(y - 19), (short)(0.15 * (w-20)), 19, + uiDefButS(block, TOG, 1, "Level", + (short)(x + 10 + 0.65 * (w-20)), (short)(y - 19), (short)(0.20 * (w-20)), 19, &sens->level, 0.0, 0.0, 0, 0, - "Level detector versus edge detector (only applicable in case of logic state transition)"); + "Level detector, trigger controllers of new states (only applicable upon logic state transition)"); } static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short yco, short width,char* objectname) @@ -1270,15 +1270,15 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short if(ps->type == SENS_PROP_INTERVAL) { uiDefBut(block, TEX, 1, "Min: ", xco,yco-92,width/2, 19, - ps->value, 0, 31, 0, 0, "test for min value"); + ps->value, 0, 31, 0, 0, "check for min value"); uiDefBut(block, TEX, 1, "Max: ", xco+width/2,yco-92,width/2, 19, - ps->maxvalue, 0, 31, 0, 0, "test for max value"); + ps->maxvalue, 0, 31, 0, 0, "check for max value"); } else if(ps->type == SENS_PROP_CHANGED); else { uiDefBut(block, TEX, 1, "Value: ", xco+30,yco-92,width-60, 19, - ps->value, 0, 31, 0, 0, "test for value"); + ps->value, 0, 31, 0, 0, "check for value"); } yco-= ysize; @@ -1447,7 +1447,7 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short uiDefButS(block, NUM, 1, "Index:", xco+10, yco-44, 0.6 * (width-120), 19, &joy->joyindex, 0, SENS_JOY_MAXINDEX-1, 100, 0, - "Spesify which joystick to use"); + "Specify which joystick to use"); str= "Type %t|Button %x0|Axis %x1|Hat%x2"; uiDefButS(block, MENU, B_REDR, str, xco+87, yco-44, 0.6 * (width-150), 19, @@ -1891,12 +1891,12 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh else { uiDefButI(block, NUM, 0, "Sta", xco+10, yco-44, (width-80)/2, 19, - &ia->sta, 0.0, MAXFRAMEF, 0, 0, - "Start frame, (subtract 1 to match blenders frame numbers)"); + &ia->sta, 1.0, MAXFRAMEF, 0, 0, + "Start frame"); uiDefButI(block, NUM, 0, "End", xco+10+(width-80)/2, yco-44, (width-80)/2, 19, - &ia->end, 0.0, MAXFRAMEF, 0, 0, - "End frame, (subtract 1 to match blenders frame numbers)"); + &ia->end, 1.0, MAXFRAMEF, 0, 0, + "End frame"); } uiDefButBitS(block, TOG, ACT_IPOCHILD, B_REDR, "Child", xco+10+(width-80), yco-44, 60, 19, @@ -1925,7 +1925,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh uiDefBut(block, TEX, 1, "Prop: ", xco+10+(width-20)/2, yco-64, (width-20)/2, 19, pa->value, 0, 31, 0, 0, "Copy this property"); } else { - uiDefBut(block, TEX, 1, "Value: ", xco+30,yco-64,width-60, 19, pa->value, 0, 31, 0, 0, "change with this value"); + uiDefBut(block, TEX, 1, "Value: ", xco+30,yco-64,width-60, 19, pa->value, 0, 31, 0, 0, "change with this value, use \"\" around strings"); } yco-= ysize; @@ -3168,7 +3168,7 @@ void logic_buts(void) but= uiDefBut(block, BUT, 1, "Del", 10, (short)(50-20*a), 40, 20, NULL, 0.0, 0.0, 1, (float)a, ""); uiButSetFunc(but, del_property, prop, NULL); uiDefButS(block, MENU, B_CHANGE_PROP, pupstr, 50, (short)(50-20*a), 60, 20, &prop->type, 0, 0, 0, 0, ""); - but= uiDefBut(block, TEX, 1, "Name:", 110, (short)(50-20*a), 110, 20, prop->name, 0, 31, 0, 0, ""); + but= uiDefBut(block, TEX, 1, "Name:", 110, (short)(50-20*a), 110, 20, prop->name, 0, 31, 0, 0, "Available as GameObject attributes in the game engines python api"); uiButSetFunc(but, make_unique_prop_names_cb, prop->name, (void*) 1); if(prop->type==PROP_BOOL) { @@ -3311,7 +3311,7 @@ void logic_buts(void) uiDefIconButBitS(block, ICONTOG, CONT_SHOW, B_REDR, ICON_RIGHTARROW, (short)(xco+width-22), yco, 22, 19, &cont->flag, 0, 0, 0, 0, "Controller settings"); uiBlockSetEmboss(block, UI_EMBOSSP); sprintf(name, "%d", first_bit(cont->state_mask)+1); - uiDefBlockBut(block, controller_state_mask_menu, cont, name, (short)(xco+width-44), yco, 22, 19, "Set controller state mask"); + uiDefBlockBut(block, controller_state_mask_menu, cont, name, (short)(xco+width-44), yco, 22, 19, "Set controller state index (from 1 to 30)"); uiBlockSetEmboss(block, UI_EMBOSSM); if(cont->flag & CONT_SHOW) { From e5ce1e962ddd1fd3b1850dfede3884f321d95974 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Mon, 15 Sep 2008 09:24:54 +0000 Subject: [PATCH 077/125] copy menu didnt copy visible and initial states, physics margin was also missing from "all physical attributes" option --- source/blender/src/editobject.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/src/editobject.c b/source/blender/src/editobject.c index e05d1c519d5..2459f7ed23c 100644 --- a/source/blender/src/editobject.c +++ b/source/blender/src/editobject.c @@ -3283,6 +3283,9 @@ static void copymenu_logicbricks(Object *ob) base->object->scavisflag= ob->scavisflag; base->object->scaflag= ob->scaflag; + /* set the initial state */ + base->object->state= ob->state; + base->object->init_state= ob->init_state; } } base= base->next; @@ -3519,6 +3522,7 @@ void copy_attr(short event) if (ob->gameflag & OB_BOUNDS) { base->object->boundtype = ob->boundtype; } + base->object->margin= ob->margin; } else if(event==17) { /* tex space */ copy_texture_space(base->object, ob); From fd3a40a12969085c16927bd2b2240f9ac98d951f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 15 Sep 2008 11:39:49 +0000 Subject: [PATCH 078/125] Fix glsl vertex shader string that was not 0 terminated, no idea if it caused any problems. --- source/blender/gpu/intern/gpu_shader_vertex.glsl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/gpu/intern/gpu_shader_vertex.glsl.c b/source/blender/gpu/intern/gpu_shader_vertex.glsl.c index a89de776864..edf93d838d5 100644 --- a/source/blender/gpu/intern/gpu_shader_vertex.glsl.c +++ b/source/blender/gpu/intern/gpu_shader_vertex.glsl.c @@ -9,5 +9,5 @@ char datatoc_gpu_shader_vertex_glsl[]= { 110, 32, 61, 32, 99,111, 46,120,121,122, 59, 10, 9,118, 97,114,110,111,114,109, 97,108, 32, 61, 32,103,108, 95, 78,111,114,109, 97,108, 77, 97,116,114,105,120, 32, 42, 32,103,108, 95, 78,111,114,109, 97,108, 59, 10, 9,103,108, 95, 80,111,115,105,116,105, 111,110, 32, 61, 32,103,108, 95, 80,114,111,106,101, 99,116,105,111,110, 77, 97,116,114,105,120, 32, 42, 32, 99,111, 59, 10, 10, -}; + 0}; From dc2594c81b5d67cc290f88ca846c5285ba45a412 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 15 Sep 2008 12:40:17 +0000 Subject: [PATCH 079/125] Added -d debug option for blenderplayer, and remove some invalid/unnecessary opengl calls on shader errors. --- source/blender/gpu/intern/gpu_extensions.c | 3 --- source/gameengine/GamePlayer/ghost/GPG_ghost.cpp | 8 ++++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index d900f9c63f2..c6e9c5aeafd 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -706,7 +706,6 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, GPUSh glGetObjectParameterivARB(shader->vertex, GL_OBJECT_COMPILE_STATUS_ARB, &status); if (!status) { - glValidateProgramARB(shader->vertex); glGetInfoLogARB(shader->vertex, sizeof(log), &length, log); shader_print_errors("compile", log, vertexcode); @@ -723,7 +722,6 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, GPUSh glGetObjectParameterivARB(shader->fragment, GL_OBJECT_COMPILE_STATUS_ARB, &status); if (!status) { - glValidateProgramARB(shader->fragment); glGetInfoLogARB(shader->fragment, sizeof(log), &length, log); shader_print_errors("compile", log, fragcode); @@ -771,7 +769,6 @@ GPUShader *GPU_shader_create_lib(const char *code) glGetObjectParameterivARB(shader->lib, GL_OBJECT_COMPILE_STATUS_ARB, &status); if (!status) { - glValidateProgramARB(shader->lib); glGetInfoLogARB(shader->lib, sizeof(log), &length, log); shader_print_errors("compile", log, code); diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index c4e738c1896..8fd23318df1 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -52,6 +52,7 @@ extern "C" { #endif // __cplusplus +#include "MEM_guardedalloc.h" #include "BKE_global.h" #include "BKE_icons.h" #include "BKE_node.h" @@ -185,6 +186,7 @@ void usage(char* program) #ifdef _WIN32 printf(" -c: keep console window open\n"); #endif + printf(" -d: turn debugging on\n"); printf(" -g: game engine options:\n"); printf(" Name Default Description\n"); printf(" ----------------------------------------\n"); @@ -414,6 +416,12 @@ int main(int argc, char** argv) } } break; + + case 'd': + i++; + G.f |= G_DEBUG; /* std output printf's */ + MEM_set_memory_debug(); + break; case 'p': // Parse window position and size options From cffba77f50455b300efba1de834e2f8edca64519 Mon Sep 17 00:00:00 2001 From: Kent Mein Date: Mon, 15 Sep 2008 15:58:50 +0000 Subject: [PATCH 080/125] Small tweak to get things compiling again. Kent --- source/gameengine/GamePlayer/ghost/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/source/gameengine/GamePlayer/ghost/Makefile b/source/gameengine/GamePlayer/ghost/Makefile index 0b187791734..52e219db8f2 100644 --- a/source/gameengine/GamePlayer/ghost/Makefile +++ b/source/gameengine/GamePlayer/ghost/Makefile @@ -41,6 +41,7 @@ CPPFLAGS += -I$(OPENGL_HEADERS) CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_BMFONT)/include CPPFLAGS += -I$(NAN_SOUNDSYSTEM)/include +CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include CPPFLAGS += -I../../GamePlayer/common From 35c269e3955785dac254cf9a735860e935b3ae63 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Mon, 15 Sep 2008 18:15:11 +0000 Subject: [PATCH 081/125] Workaround for an Nvidia driver bug on 32 bit linux (maybe windows too). I reversed the order of attaching shader objects for linking to solve an issue in the driver before, but now it appears it needs to be the other way around again? I don't know if these are the same cards that now want it different again due to changes in the glsl code, but I found another workaround for the first bug in a forum post (leaving out parameter names in the declarations), so with some luck both cases work? http://developer.nvidia.com/forums/index.php?showtopic=596 --- source/blender/gpu/intern/gpu_codegen.c | 2 +- source/blender/gpu/intern/gpu_extensions.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 00efe6e1572..78a99cab447 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -331,7 +331,7 @@ static char *gpu_generate_function_prototyps(GHash *hash) else BLI_dynstr_append(ds, GPU_DATATYPE_STR[function->paramtype[a]]); - BLI_dynstr_printf(ds, " param%d", a); + //BLI_dynstr_printf(ds, " param%d", a); if(a != function->totparam-1) BLI_dynstr_append(ds, ", "); diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index c6e9c5aeafd..4c3090dd2c1 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -695,9 +695,6 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, GPUSh return NULL; } - if(lib && lib->lib) - glAttachObjectARB(shader->object, lib->lib); - if(vertexcode) { glAttachObjectARB(shader->object, shader->vertex); glShaderSourceARB(shader->vertex, 1, (const char**)&vertexcode, NULL); @@ -730,6 +727,9 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, GPUSh } } + if(lib && lib->lib) + glAttachObjectARB(shader->object, lib->lib); + glLinkProgramARB(shader->object); glGetObjectParameterivARB(shader->object, GL_OBJECT_LINK_STATUS_ARB, &status); if (!status) { From aae506aea70ebf537c7b6079cd13ada6742fc176 Mon Sep 17 00:00:00 2001 From: Diego Borghetti Date: Mon, 15 Sep 2008 18:23:34 +0000 Subject: [PATCH 082/125] Small fix in GHOST X11 system. * Fix and a little of cleanup to the full screen, minimzed and maximized code. * Fix bad argument in the ClientMessage event to support the _NET_ACTIVE_WINDOW property. * Fix focus problem in some WM (like TWM), this is because Blender don't set the WM_PROTOCOLS list, now it does, a very basic list but it's what we need now. --- intern/ghost/intern/GHOST_SystemX11.cpp | 47 ++- intern/ghost/intern/GHOST_SystemX11.h | 22 +- intern/ghost/intern/GHOST_WindowX11.cpp | 399 ++++++++++++++++++++---- intern/ghost/intern/GHOST_WindowX11.h | 21 ++ 4 files changed, 419 insertions(+), 70 deletions(-) diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 1b90831986d..047bc654559 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -96,15 +96,26 @@ 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", True); + m_delete_window_atom = XInternAtom(m_display, "WM_DELETE_WINDOW", False); #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; if (gettimeofday(&tv,NULL) == -1) { @@ -477,7 +488,7 @@ GHOST_SystemX11::processEvent(XEvent *xe) XClientMessageEvent & xcme = xe->xclient; #ifndef __sgi - if (xcme.data.l[0] == m_delete_window_atom) { + if (((Atom)xcme.data.l[0]) == m_delete_window_atom) { g_event = new GHOST_Event( getMilliSeconds(), @@ -511,6 +522,14 @@ GHOST_SystemX11::processEvent(XEvent *xe) GHOST_kEventNDOFButton, window, data); } + } + 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). + */ + XSetInputFocus(m_display, xcme.window, RevertToParent, xcme.data.l[1]); } else { /* Unknown client message, ignore */ } @@ -528,6 +547,24 @@ 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 c67f7d81e60..683337b47e1 100644 --- a/intern/ghost/intern/GHOST_SystemX11.h +++ b/intern/ghost/intern/GHOST_SystemX11.h @@ -215,15 +215,27 @@ 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 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_delete_window_atom; + private : Display * m_display; - /** - * Atom used to detect window close events - */ - Atom m_delete_window_atom; - /// The vector of windows that need to be updated. std::vector m_dirty_windows; diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 7b0606c40b7..2f7aee95b82 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -54,6 +54,16 @@ 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 @@ -154,7 +164,8 @@ 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; @@ -228,7 +239,6 @@ GHOST_WindowX11( Window root_return; int x_return,y_return; unsigned int w_return,h_return,border_w_return,depth_return; - GHOST_TInt32 screen_x, screen_y; XGetGeometry(m_display, parentWindow, &root_return, &x_return, &y_return, &w_return, &h_return, &border_w_return, &depth_return ); @@ -262,46 +272,26 @@ GHOST_WindowX11( // Are we in fullscreen mode - then include // some obscure blut code to remove decorations. - if (state == GHOST_kWindowStateFullScreen) { + /* + * 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; + } - 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. @@ -324,6 +314,25 @@ GHOST_WindowX11( free(wmclass); XFree(xclasshint); + /* The basic for a good ICCCM "work" */ + if (m_system->m_wm_protocols) { + natom= 0; + + if (m_system->m_delete_window_atom) { + atoms[natom]= m_system->m_delete_window_atom; + natom++; + } + + if (m_system->m_wm_take_focus) { + atoms[natom]= m_system->m_wm_take_focus; + natom++; + } + + if (natom) { + /* printf("Register atoms: %d\n", natom); */ + XSetWMProtocols(m_display, m_window, atoms, natom); + } + } // Set the window icon XWMHints *xwmhints = XAllocWMHints(); @@ -645,28 +654,298 @@ clientToScreen( outY = ay; } +void GHOST_WindowX11::icccmSetState(int state) +{ + XEvent xev; - GHOST_TWindowState -GHOST_WindowX11:: -getState( -) const { - //FIXME - return GHOST_kWindowStateNormal; + 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); } - GHOST_TSuccess -GHOST_WindowX11:: -setState( - GHOST_TWindowState state -){ - //TODO +int GHOST_WindowX11::icccmGetState(void) const +{ + unsigned char *prop_ret; + unsigned long bytes_after, num_ret; + Atom type_ret; + int format_ret, st; - if (state == (int)getState()) { - return GHOST_kSuccess; - } else { - return GHOST_kFailure; + 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_TSuccess GHOST_WindowX11::setState(GHOST_TWindowState state) +{ + GHOST_TWindowState cur_state; + bool is_max, is_full, is_motif_full; + + cur_state = getState(); + if (state == (int)cur_state) + 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); + } + + return (GHOST_kFailure); } #include @@ -701,9 +980,9 @@ setOrder( xev.xclient.message_type = atom; xev.xclient.format = 32; - xev.xclient.data.l[0] = 0; - xev.xclient.data.l[1] = 0; - xev.xclient.data.l[2] = 0; + xev.xclient.data.l[0] = 1; + xev.xclient.data.l[1] = CurrentTime; + xev.xclient.data.l[2] = m_window; xev.xclient.data.l[3] = 0; xev.xclient.data.l[4] = 0; diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index abb5c131cb7..1d73faaf3f6 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -212,6 +212,15 @@ 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. @@ -327,6 +336,18 @@ 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; }; From 95afafb5e5bb2efcc511425193d27ae389866594 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Mon, 15 Sep 2008 21:10:51 +0000 Subject: [PATCH 083/125] BGE bug #17621 fixed: State Actuator GUI Flaw. State actuator didn't behave like the object state mask. Now it works the same: LMB select one state, deselects all others, multiple select with SHIFT-LMB --- source/blender/src/buttons_logic.c | 31 ++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index d75eaeb2fbb..ceb93241d5a 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -1647,6 +1647,16 @@ char *get_state_name(Object *ob, short bit) return (char*)""; } +static void check_state_mask(void *arg1_but, void *arg2_mask) +{ + unsigned int *cont_mask = arg2_mask; + uiBut *but = arg1_but; + + if (*cont_mask == 0 || !(G.qual & LR_SHIFTKEY)) + *cont_mask = (1<retval); + but->retval = B_REDR; +} + static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, short xco, short yco, short width) { bSoundActuator *sa = NULL; @@ -1674,6 +1684,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh int myline, stbit; uiBut *but; + /* yco is at the top of the rect, draw downwards */ uiBlockSetEmboss(block, UI_EMBOSSM); set_col_actuator(act->type, 0); @@ -2380,10 +2391,12 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh for (wval=0; wval<15; wval+=5) { uiBlockBeginAlign(block); for (stbit=0; stbit<5; stbit++) { - uiDefButBitI(block, TOG, (1<<(stbit+wval)), 0, "", (short)(xco+85+12*stbit+13*wval), yco-17, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(wval+stbit))); + but = uiDefButBitI(block, TOG, 1<<(stbit+wval), stbit+wval, "", (short)(xco+85+12*stbit+13*wval), yco-17, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+wval))); + uiButSetFunc(but, check_state_mask, but, &(staAct->mask)); } for (stbit=0; stbit<5; stbit++) { - uiDefButBitI(block, TOG, (1<<(stbit+wval+15)), 0, "", (short)(xco+85+12*stbit+13*wval), yco-29, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(wval+stbit+15))); + but = uiDefButBitI(block, TOG, 1<<(stbit+wval+15), stbit+wval+15, "", (short)(xco+85+12*stbit+13*wval), yco-29, 12, 12, (int *)&(staAct->mask), 0, 0, 0, 0, get_state_name(ob, (short)(stbit+wval+15))); + uiButSetFunc(but, check_state_mask, but, &(staAct->mask)); } } uiBlockEndAlign(block); @@ -2990,16 +3003,6 @@ void buttons_bullet(uiBlock *block, Object *ob) } } -static void check_object_state(void *arg1_but, void *arg2_mask) -{ - unsigned int *cont_mask = arg2_mask; - uiBut *but = arg1_but; - - if (*cont_mask == 0 || !(G.qual & LR_SHIFTKEY)) - *cont_mask = (1<retval); - but->retval = B_REDR; -} - static void check_controller_state_mask(void *arg1_but, void *arg2_mask) { unsigned int *cont_mask = arg2_mask; @@ -3273,11 +3276,11 @@ void logic_buts(void) 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))); - uiButSetFunc(but, check_object_state, but, &(ob->state)); + 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))); - uiButSetFunc(but, check_object_state, but, &(ob->state)); + uiButSetFunc(but, check_state_mask, but, &(ob->state)); } } uiBlockBeginAlign(block); From f807d3f303a26114bf3e10ef4d89cd3c32be5ae9 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Mon, 15 Sep 2008 21:37:27 +0000 Subject: [PATCH 084/125] BGE bug #17565 fixed: Constraint Actuator Location: GUI broken. Axis selection was not persistent, now it is. --- source/blender/src/buttons_logic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index ceb93241d5a..5a689050ff0 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -2132,7 +2132,7 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh /* str= "Limit %t|None %x0|Loc X %x1|Loc Y %x2|Loc Z %x4|Rot X %x8|Rot Y %x16|Rot Z %x32"; */ /* coa->flag &= ~(63); */ str= "Limit %t|None %x0|Loc X %x1|Loc Y %x2|Loc Z %x4"; - coa->flag &= ~(7); + coa->flag &= 7; coa->time = 0; uiDefButS(block, MENU, 1, str, xco+10, yco-65, 70, 19, &coa->flag, 0.0, 0.0, 0, 0, ""); From 4683cb34e4de119d726a44e15ce683917cfd0610 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Mon, 15 Sep 2008 22:08:30 +0000 Subject: [PATCH 085/125] Fix for #17618 Particles: changing RGB sliders snap back -particle drawing was reading material ipos in a too invasive way --- source/blender/blenkernel/intern/particle.c | 21 ++++-- source/blender/src/drawobject.c | 78 +++++++++++++-------- 2 files changed, 65 insertions(+), 34 deletions(-) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index db3576f0c50..2678608fb9a 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -46,6 +46,7 @@ #include "DNA_object_types.h" #include "DNA_curve_types.h" #include "DNA_key_types.h" +#include "DNA_ipo_types.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -3377,16 +3378,24 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra, float size, time; if(part->childtype==PART_CHILD_FACES){ - if(pa_time) - time=*pa_time; - else - time=psys_get_child_time(psys,cpa,cfra); + size=part->size; if((part->flag&PART_ABS_TIME)==0 && part->ipo){ + IpoCurve *icu; + + if(pa_time) + time=*pa_time; + else + time=psys_get_child_time(psys,cpa,cfra); + + /* correction for lifetime */ calc_ipo(part->ipo, 100*time); - execute_ipo((ID *)part, part->ipo); + + for(icu = part->ipo->curve.first; icu; icu=icu->next) { + if(icu->adrcode == PART_SIZE) + size = icu->curval; + } } - size=part->size; } else size=psys->particles[cpa->parent].size; diff --git a/source/blender/src/drawobject.c b/source/blender/src/drawobject.c index 4876e6cae7c..8a3176e16b2 100644 --- a/source/blender/src/drawobject.c +++ b/source/blender/src/drawobject.c @@ -2911,6 +2911,7 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) float timestep, pixsize=1.0, pa_size, pa_time, r_tilt; float cfra=bsystem_time(ob,(float)CFRA,0.0); float *vdata=0, *vedata=0, *cdata=0, *ndata=0, *vd=0, *ved=0, *cd=0, *nd=0, xvec[3], yvec[3], zvec[3]; + float ma_r=0.0f, ma_g=0.0f, ma_b=0.0f; int a, k, k_max=0, totpart, totpoint=0, draw_as, path_nbr=0; int path_possible=0, keys_possible=0, draw_keys=0, totchild=0; int select=ob->flag&SELECT, create_cdata=0; @@ -2963,6 +2964,12 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) ma= give_current_material(ob,part->omat); + if(ma) { + ma_r = ma->r; + ma_g = ma->g; + ma_b = ma->b; + } + if(G.vd->zbuf) glDepthMask(1); if(select) @@ -2989,11 +2996,6 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) totpart=psys->totpart; draw_as=part->draw_as; - if(part->flag&PART_ABS_TIME && part->ipo){ - calc_ipo(part->ipo, cfra); - execute_ipo((ID *)part, part->ipo); - } - if(part->flag&PART_GLOB_TIME) cfra=bsystem_time(0,(float)CFRA,0.0); @@ -3120,22 +3122,37 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) if(pa->flag & PARS_NO_DISP || pa->flag & PARS_UNEXIST) continue; pa_time=(cfra-pa->time)/pa->lifetime; + pa_size=pa->size; if((part->flag&PART_ABS_TIME)==0){ if(ma && ma->ipo){ + IpoCurve *icu; + /* correction for lifetime */ calc_ipo(ma->ipo, 100.0f*pa_time); - execute_ipo((ID *)ma, ma->ipo); + + for(icu = ma->ipo->curve.first; icu; icu=icu->next) { + if(icu->adrcode == MA_COL_R) + ma_r = icu->curval; + else if(icu->adrcode == MA_COL_G) + ma_g = icu->curval; + else if(icu->adrcode == MA_COL_B) + ma_b = icu->curval; + } } if(part->ipo) { + IpoCurve *icu; + /* correction for lifetime */ calc_ipo(part->ipo, 100*pa_time); - execute_ipo((ID *)part, part->ipo); + + for(icu = part->ipo->curve.first; icu; icu=icu->next) { + if(icu->adrcode == PART_SIZE) + pa_size = icu->curval; + } } } - pa_size=pa->size; - r_tilt=1.0f+pa->r_ave[0]; if(path_nbr){ @@ -3150,14 +3167,19 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) if((part->flag&PART_ABS_TIME)==0) { if(ma && ma->ipo){ + IpoCurve *icu; + /* correction for lifetime */ calc_ipo(ma->ipo, 100.0f*pa_time); - execute_ipo((ID *)ma, ma->ipo); - } - if(part->ipo) { - /* correction for lifetime */ - calc_ipo(part->ipo, 100*pa_time); - execute_ipo((ID *)part, part->ipo); + + for(icu = ma->ipo->curve.first; icu; icu=icu->next) { + if(icu->adrcode == MA_COL_R) + ma_r = icu->curval; + else if(icu->adrcode == MA_COL_G) + ma_g = icu->curval; + else if(icu->adrcode == MA_COL_B) + ma_b = icu->curval; + } } } @@ -3197,9 +3219,9 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) switch(draw_as){ case PART_DRAW_DOT: if(cd) { - cd[0]=ma->r; - cd[1]=ma->g; - cd[2]=ma->b; + cd[0]=ma_r; + cd[1]=ma_g; + cd[2]=ma_b; cd+=3; } if(vd){ @@ -3224,9 +3246,9 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) } else { if(cd) { - cd[0]=cd[3]=cd[6]=cd[9]=cd[12]=cd[15]=ma->r; - cd[1]=cd[4]=cd[7]=cd[10]=cd[13]=cd[16]=ma->g; - cd[2]=cd[5]=cd[8]=cd[11]=cd[14]=cd[17]=ma->b; + cd[0]=cd[3]=cd[6]=cd[9]=cd[12]=cd[15]=ma_r; + cd[1]=cd[4]=cd[7]=cd[10]=cd[13]=cd[16]=ma_g; + cd[2]=cd[5]=cd[8]=cd[11]=cd[14]=cd[17]=ma_b; cd+=18; } VECSUB(vec2,state.co,vec); @@ -3269,22 +3291,22 @@ static void draw_new_particle_system(Base *base, ParticleSystem *psys, int dt) VECADDFAC(vd,state.co,vec,-part->draw_line[0]); vd+=3; VECADDFAC(vd,state.co,vec,part->draw_line[1]); vd+=3; if(cd) { - cd[0]=cd[3]=ma->r; - cd[1]=cd[4]=ma->g; - cd[2]=cd[5]=ma->b; + cd[0]=cd[3]=ma_r; + cd[1]=cd[4]=ma_g; + cd[2]=cd[5]=ma_b; cd+=3; } break; case PART_DRAW_CIRC: if(create_cdata) - glColor3f(ma->r,ma->g,ma->b); + glColor3f(ma_r,ma_g,ma_b); drawcircball(GL_LINE_LOOP, state.co, pixsize, imat); break; case PART_DRAW_BB: if(cd) { - cd[0]=cd[3]=cd[6]=cd[9]=ma->r; - cd[1]=cd[4]=cd[7]=cd[10]=ma->g; - cd[2]=cd[5]=cd[8]=cd[11]=ma->b; + cd[0]=cd[3]=cd[6]=cd[9]=ma_r; + cd[1]=cd[4]=cd[7]=cd[10]=ma_g; + cd[2]=cd[5]=cd[8]=cd[11]=ma_b; cd+=12; } if(part->draw&PART_DRAW_BB_LOCK && part->bb_align==PART_BB_VIEW){ From 9031ef3e8704526db94027f0311ba0b7613afd88 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 16 Sep 2008 02:58:33 +0000 Subject: [PATCH 086/125] Fix for bug #12028: background rendering on Mac OS X without a window manager did not work anymore since 2.46. --- source/creator/creator.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/source/creator/creator.c b/source/creator/creator.c index bdd16dc6bed..f27dee946ed 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -267,7 +267,7 @@ static void main_init_screen( void ) int main(int argc, char **argv) { - int a, i, stax=0, stay=0, sizx, sizy, scr_init = 0; + int a, i, stax, stay, sizx, sizy, scr_init = 0; SYS_SystemHandle syshandle; #if defined(WIN32) || defined (__linux__) @@ -301,10 +301,10 @@ int main(int argc, char **argv) setprefsize(left +10,scr_y - bottom +10,right-left -20,bottom - 64, 0); } else { - winlay_get_screensize(&scr_x, &scr_y); + winlay_get_screensize(&scr_x, &scr_y); - /* 40 + 684 + (headers) 22 + 22 = 768, the powerbook screen height */ - setprefsize(120, 40, 850, 684, 0); + /* 40 + 684 + (headers) 22 + 22 = 768, the powerbook screen height */ + setprefsize(120, 40, 850, 684, 0); } winlay_process_events(0); @@ -430,11 +430,11 @@ int main(int argc, char **argv) init_def_material(); - winlay_get_screensize(&sizx, &sizy); - stax=0; - stay=0; - if(G.background==0) { + winlay_get_screensize(&sizx, &sizy); + stax=0; + stay=0; + for(a=1; a Date: Tue, 16 Sep 2008 06:11:02 +0000 Subject: [PATCH 087/125] Bugfix #17627: Autokeyframe for Visual keying Several months old typo! 'Visual keying' was not working for autokeyframing, as the test for it didn't even work. --- source/blender/makesdna/DNA_userdef_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 981591dc810..2474161da07 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -292,7 +292,7 @@ extern UserDef U; /* from usiblender.c !!!! */ /* Auto-Keying macros */ #define IS_AUTOKEY_ON (U.autokey_mode & AUTOKEY_ON) #define IS_AUTOKEY_MODE(mode) (U.autokey_mode == AUTOKEY_MODE_##mode) -#define IS_AUTOKEY_FLAG(flag) (U.autokey_flag == AUTOKEY_FLAG_##flag) +#define IS_AUTOKEY_FLAG(flag) (U.autokey_flag & AUTOKEY_FLAG_##flag) /* transopts */ #define USER_TR_TOOLTIPS (1 << 0) From 0f39be9ce832894443a728dedf86c82d8cb59d84 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 16 Sep 2008 06:31:55 +0000 Subject: [PATCH 088/125] added static openal and openexr options for scons. also added a target 'blenderlite' - turns almost everything off, compressed binary is ~3.4meg --- SConstruct | 17 +++++++++++++++++ config/darwin-config.py | 8 +++++++- config/linux2-config.py | 7 +++++++ config/linuxcross-config.py | 6 ++++++ config/openbsd3-config.py | 5 +++++ config/sunos5-config.py | 6 ++++++ config/win32-mingw-config.py | 6 ++++++ config/win32-vc-config.py | 6 ++++++ tools/Blender.py | 18 +++++++++++++----- tools/btools.py | 13 ++++++++++--- 10 files changed, 83 insertions(+), 9 deletions(-) diff --git a/SConstruct b/SConstruct index 4c3bbf8fad7..92547bf6756 100644 --- a/SConstruct +++ b/SConstruct @@ -248,6 +248,19 @@ if 'blenderplayer' in B.targets: if 'blendernogame' in B.targets: env['WITH_BF_GAMEENGINE'] = False +if 'blenderlite' in B.targets: + env['WITH_BF_GAMEENGINE'] = False + env['WITH_BF_OPENAL'] = False + env['WITH_BF_OPENEXR'] = False + env['WITH_BF_ICONV'] = False + env['WITH_BF_INTERNATIONAL'] = False + env['WITH_BF_OPENJPEG'] = False + env['WITH_BF_FFMPEG'] = False + env['WITH_BF_QUICKTIME'] = False + env['WITH_BF_YAFRAY'] = False + env['WITH_BF_REDCODE'] = False + env['WITH_BF_FTGL'] = False + # lastly we check for root_build_dir ( we should not do before, otherwise we might do wrong builddir #B.root_build_dir = B.arguments.get('BF_BUILDDIR', '..'+os.sep+'build'+os.sep+platform+os.sep) B.root_build_dir = env['BF_BUILDDIR'] @@ -488,6 +501,10 @@ if not env['WITH_BF_GAMEENGINE']: blendernogame = env.Alias('blendernogame', B.program_list) Depends(blendernogame,installtarget) +if 'blenderlite' in B.targets: + blenderlite = env.Alias('blenderlite', B.program_list) + Depends(blenderlite,installtarget) + Depends(nsiscmd, allinstall) Default(B.program_list) diff --git a/config/darwin-config.py b/config/darwin-config.py index 48455d2ce8c..70d2281b1f7 100644 --- a/config/darwin-config.py +++ b/config/darwin-config.py @@ -87,10 +87,13 @@ if MAC_PROC == 'powerpc': BF_OPENAL = '#../lib/darwin-8.0.0-powerpc/openal' else : BF_OPENAL = LIBDIR + '/openal' - + +WITH_BF_STATICOPENAL = 'false' BF_OPENAL_INC = '${BF_OPENAL}/include' BF_OPENAL_LIB = 'openal' BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' WITH_BF_SDL = 'true' BF_SDL = LIBDIR + '/sdl' #$(shell sdl-config --prefix) @@ -102,10 +105,13 @@ WITH_BF_FMOD = 'false' BF_FMOD = LIBDIR + '/fmod' WITH_BF_OPENEXR = 'true' +WITH_BF_STATICOPENEXR = 'false' BF_OPENEXR = '${LCGDIR}/openexr' BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR' BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread' BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' WITH_BF_DDS = 'true' diff --git a/config/linux2-config.py b/config/linux2-config.py index 36cbac6df10..f2df9b86c6b 100644 --- a/config/linux2-config.py +++ b/config/linux2-config.py @@ -14,12 +14,16 @@ BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic'] BF_PYTHON_LIB_STATIC = '${BF_PYTHON}/lib/libpython${BF_PYTHON_VERSION}.a' WITH_BF_OPENAL = 'true' +WITH_BF_STATICOPENAL = 'false' BF_OPENAL = '/usr' BF_OPENAL_INC = '${BF_OPENAL}/include' BF_OPENAL_LIB = 'openal' +BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' + # some distros have a separate libalut # if you get linker complaints, you need to uncomment the line below # BF_OPENAL_LIB = 'openal alut' +# BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a ${BF_OPENAL}/lib/libalut.a' WITH_BF_SDL = 'true' BF_SDL = '/usr' #$(shell sdl-config --prefix) @@ -30,14 +34,17 @@ WITH_BF_FMOD = 'false' BF_FMOD = LIBDIR + '/fmod' WITH_BF_OPENEXR = 'true' +WITH_BF_STATICOPENEXR = 'false' BF_OPENEXR = '/usr' # when compiling with your own openexr lib you might need to set... # BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR ${BF_OPENEXR}/include' BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR' BF_OPENEXR_LIB = 'Half IlmImf Iex Imath ' +BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' # BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' + WITH_BF_DDS = 'true' WITH_BF_JPEG = 'true' diff --git a/config/linuxcross-config.py b/config/linuxcross-config.py index e6c4e8769b4..3172a4a060c 100644 --- a/config/linuxcross-config.py +++ b/config/linuxcross-config.py @@ -14,10 +14,13 @@ BF_PYTHON_LIB = 'python25' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' WITH_BF_OPENAL = 'true' +WITH_BF_STATICOPENAL = 'false' BF_OPENAL = LIBDIR + '/openal' BF_OPENAL_INC = '${BF_OPENAL}/include' BF_OPENAL_LIB = 'openal_static' BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' WITH_BF_SDL = 'true' BF_SDL = LIBDIR + '/sdl' @@ -34,10 +37,13 @@ WITH_BF_FMOD = 'false' BF_FMOD = LIBDIR + '/fmod' WITH_BF_OPENEXR = 'true' +WITH_BF_STATICOPENEXR = 'false' BF_OPENEXR = LIBDIR + '/gcc/openexr' BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR' BF_OPENEXR_LIB = ' Half IlmImf Iex ' BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' WITH_BF_DDS = 'true' diff --git a/config/openbsd3-config.py b/config/openbsd3-config.py index f7f254973af..5ef3d90f168 100644 --- a/config/openbsd3-config.py +++ b/config/openbsd3-config.py @@ -9,10 +9,12 @@ BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib/python${BF_PYTHON_VERSION}/config' WITH_BF_OPENAL = 'false' +# WITH_BF_STATICOPENAL = 'false' #BF_OPENAL = LIBDIR + '/openal' #BF_OPENAL_INC = '${BF_OPENAL}/include' #BF_OPENAL_LIB = 'openal' #BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' +#BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' WITH_BF_SDL = 'true' BF_SDL = '/usr/local' #$(shell sdl-config --prefix) @@ -24,9 +26,12 @@ WITH_BF_FMOD = 'false' BF_FMOD = LIBDIR + '/fmod' WITH_BF_OPENEXR = 'false' +WITH_BF_STATICOPENEXR = 'false' BF_OPENEXR = '/usr/local' BF_OPENEXR_INC = '${BF_OPENEXR}/include/OpenEXR' BF_OPENEXR_LIB = 'Half IlmImf Iex Imath ' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' WITH_BF_DDS = 'true' diff --git a/config/sunos5-config.py b/config/sunos5-config.py index b3ca0e267ff..84e2f57bd3e 100644 --- a/config/sunos5-config.py +++ b/config/sunos5-config.py @@ -9,10 +9,13 @@ BF_PYTHON_LIB = 'python${BF_PYTHON_VERSION}' #BF_PYTHON+'/lib/python'+BF_PYTHON_ BF_PYTHON_LINKFLAGS = ['-Xlinker', '-export-dynamic'] WITH_BF_OPENAL = 'true' +WITH_BF_STATICOPENAL = 'false' BF_OPENAL = '/usr/local' BF_OPENAL_INC = '${BF_OPENAL}/include' BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' BF_OPENAL_LIB = 'openal' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' WITH_BF_SDL = 'true' BF_SDL = '/usr/local' #$(shell sdl-config --prefix) @@ -24,10 +27,13 @@ WITH_BF_FMOD = 'false' BF_FMOD = LIBDIR + '/fmod' WITH_BF_OPENEXR = 'true' +WITH_BF_STATICOPENEXR = 'false' BF_OPENEXR = '/usr/local' BF_OPENEXR_INC = ['${BF_OPENEXR}/include', '${BF_OPENEXR}/include/OpenEXR' ] BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' BF_OPENEXR_LIB = 'Half IlmImf Iex Imath ' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' WITH_BF_DDS = 'true' diff --git a/config/win32-mingw-config.py b/config/win32-mingw-config.py index d9fd6ce8d4f..4ff93bf7078 100644 --- a/config/win32-mingw-config.py +++ b/config/win32-mingw-config.py @@ -12,10 +12,13 @@ BF_PYTHON_LIB = 'python25' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' WITH_BF_OPENAL = 'true' +WITH_BF_STATICOPENAL = 'false' BF_OPENAL = LIBDIR + '/openal' BF_OPENAL_INC = '${BF_OPENAL}/include' BF_OPENAL_LIB = 'dxguid openal_static' BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' WITH_BF_FFMPEG = 'false' BF_FFMPEG_LIB = 'avformat swscale avcodec avutil xvidcore x264' @@ -37,10 +40,13 @@ WITH_BF_FMOD = 'false' BF_FMOD = LIBDIR + '/fmod' WITH_BF_OPENEXR = 'true' +WITH_BF_STATICOPENEXR = 'false' BF_OPENEXR = LIBDIR + '/gcc/openexr' BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/OpenEXR' BF_OPENEXR_LIB = ' Half IlmImf Iex ' BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' WITH_BF_DDS = 'true' diff --git a/config/win32-vc-config.py b/config/win32-vc-config.py index 02e5dbb7f8f..725cd7133da 100644 --- a/config/win32-vc-config.py +++ b/config/win32-vc-config.py @@ -19,10 +19,13 @@ BF_PYTHON_LIB = 'python25' BF_PYTHON_LIBPATH = '${BF_PYTHON}/lib' WITH_BF_OPENAL = 'true' +WITH_BF_STATICOPENAL = 'false' BF_OPENAL = LIBDIR + '/openal' BF_OPENAL_INC = '${BF_OPENAL}/include ${BF_OPENAL}/include/AL ' BF_OPENAL_LIB = 'dxguid openal_static' BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' WITH_BF_ICONV = 'true' BF_ICONV = LIBDIR + '/iconv' @@ -45,10 +48,13 @@ WITH_BF_FMOD = 'false' BF_FMOD = LIBDIR + '/fmod' WITH_BF_OPENEXR = 'true' +WITH_BF_STATICOPENEXR = 'false' BF_OPENEXR = LIBDIR + '/openexr' BF_OPENEXR_INC = '${BF_OPENEXR}/include ${BF_OPENEXR}/include/IlmImf ${BF_OPENEXR}/include/Iex ${BF_OPENEXR}/include/Imath ' BF_OPENEXR_LIB = ' Iex Half IlmImf Imath IlmThread ' BF_OPENEXR_LIBPATH = '${BF_OPENEXR}/lib_msvc' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_OPENEXR_LIB_STATIC = '${BF_OPENEXR}/lib/libHalf.a ${BF_OPENEXR}/lib/libIlmImf.a ${BF_OPENEXR}/lib/libIex.a ${BF_OPENEXR}/lib/libImath.a ${BF_OPENEXR}/lib/libIlmThread.a' WITH_BF_DDS = 'true' diff --git a/tools/Blender.py b/tools/Blender.py index 3f928ff8c97..b5f32f24551 100644 --- a/tools/Blender.py +++ b/tools/Blender.py @@ -117,15 +117,21 @@ def setup_staticlibs(lenv): lenv['BF_ZLIB_LIBPATH'], lenv['BF_ICONV_LIBPATH'] ] - libincs += Split(lenv['BF_OPENEXR_LIBPATH']) + + libincs += Split(lenv['BF_FFMPEG_LIBPATH']) - + + if lenv['WITH_BF_OPENEXR']: + libincs += Split(lenv['BF_OPENEXR_LIBPATH']) + if lenv['WITH_BF_STATICOPENEXR']: + statlibs += Split(lenv['BF_OPENEXR_LIB_STATIC']) if lenv['WITH_BF_INTERNATIONAL']: libincs += Split(lenv['BF_GETTEXT_LIBPATH']) libincs += Split(lenv['BF_FREETYPE_LIBPATH']) if lenv['WITH_BF_OPENAL']: libincs += Split(lenv['BF_OPENAL_LIBPATH']) - + if lenv['WITH_BF_STATICOPENAL']: + statlibs += Split(lenv['BF_OPENAL_LIB_STATIC']) if lenv['WITH_BF_STATICOPENGL']: statlibs += Split(lenv['BF_OPENGL_LIB_STATIC']) @@ -154,13 +160,15 @@ def setup_syslibs(lenv): syslibs += Split(lenv['BF_FREETYPE_LIB']) syslibs += Split(lenv['BF_GETTEXT_LIB']) if lenv['WITH_BF_OPENAL']: - syslibs += Split(lenv['BF_OPENAL_LIB']) + if not lenv['WITH_BF_STATICOPENAL']: + syslibs += Split(lenv['BF_OPENAL_LIB']) if lenv['WITH_BF_OPENMP'] and lenv['CC'] != 'icc': syslibs += ['gomp'] if lenv['WITH_BF_ICONV']: syslibs += Split(lenv['BF_ICONV_LIB']) if lenv['WITH_BF_OPENEXR']: - syslibs += Split(lenv['BF_OPENEXR_LIB']) + if not lenv['WITH_BF_STATICOPENEXR']: + syslibs += Split(lenv['BF_OPENEXR_LIB']) if lenv['WITH_BF_FFMPEG']: syslibs += Split(lenv['BF_FFMPEG_LIB']) syslibs += Split(lenv['BF_SDL_LIB']) diff --git a/tools/btools.py b/tools/btools.py index afcc83d2002..be23b1d7024 100755 --- a/tools/btools.py +++ b/tools/btools.py @@ -28,11 +28,11 @@ def print_arguments(args, bc): def validate_arguments(args, bc): opts_list = [ 'BF_PYTHON', 'BF_PYTHON_VERSION', 'BF_PYTHON_INC', 'BF_PYTHON_BINARY', 'BF_PYTHON_LIB', 'BF_PYTHON_LIBPATH', 'BF_PYTHON_LINKFLAGS', 'WITH_BF_STATICPYTHON', 'BF_PYTHON_LIB_STATIC', - 'WITH_BF_OPENAL', 'BF_OPENAL', 'BF_OPENAL_INC', 'BF_OPENAL_LIB', 'BF_OPENAL_LIBPATH', + 'WITH_BF_OPENAL', 'BF_OPENAL', 'BF_OPENAL_INC', 'BF_OPENAL_LIB', 'BF_OPENAL_LIBPATH', 'WITH_BF_STATICOPENAL', 'BF_OPENAL_LIB_STATIC', 'WITH_BF_SDL', 'BF_SDL', 'BF_SDL_INC', 'BF_SDL_LIB', 'BF_SDL_LIBPATH', 'BF_PTHREADS', 'BF_PTHREADS_INC', 'BF_PTHREADS_LIB', 'BF_PTHREADS_LIBPATH', 'WITH_BF_FMOD', - 'WITH_BF_OPENEXR', 'BF_OPENEXR', 'BF_OPENEXR_INC', 'BF_OPENEXR_LIB', 'BF_OPENEXR_LIBPATH', + 'WITH_BF_OPENEXR', 'BF_OPENEXR', 'BF_OPENEXR_INC', 'BF_OPENEXR_LIB', 'BF_OPENEXR_LIBPATH', 'WITH_BF_STATICOPENEXR', 'BF_OPENEXR_LIB_STATIC', 'WITH_BF_DDS', 'WITH_BF_FFMPEG', 'BF_FFMPEG_LIB','BF_FFMPEG_EXTRA', 'BF_FFMPEG', 'BF_FFMPEG_INC', 'WITH_BF_JPEG', 'BF_JPEG', 'BF_JPEG_INC', 'BF_JPEG_LIB', 'BF_JPEG_LIBPATH', @@ -94,7 +94,7 @@ def print_targets(targs, bc): def validate_targets(targs, bc): valid_list = ['.', 'blender', 'blenderstatic', 'blenderplayer', 'webplugin', - 'blendernogame', 'blenderstaticnogame', 'release', + 'blendernogame', 'blenderstaticnogame', 'blenderlite', 'release', 'everything', 'clean', 'install-bin', 'install', 'nsis'] oklist = [] for t in targs: @@ -139,6 +139,7 @@ def read_opts(cfg, args): ('VERSE_BUILD_DIR', 'Target directory for intermediate files.', "${BF_BUILDDIR}/extern/verse"), ('VERSE_REGEN_PROTO', 'Whether to regenerate the protocol files', 'yes'), ('BF_DEBUG_LIBS', 'list of libraries to build with debug symbols'), + ('BF_PYTHON', 'base path for python', ''), ('BF_PYTHON_VERSION', 'Python version to use', ''), ('BF_PYTHON_INC', 'include path for Python headers', ''), @@ -148,13 +149,17 @@ def read_opts(cfg, args): ('BF_PYTHON_LIBPATH', 'Library path', ''), ('BF_PYTHON_LINKFLAGS', 'Python link flags', ''), (BoolOption('WITH_BF_STATICPYTHON', 'Staticly link to python', 'false')), + (BoolOption('BF_NO_ELBEEM', 'Disable Fluid Sim', 'false')), (BoolOption('WITH_BF_YAFRAY', 'Enable Yafray', 'true')), + (BoolOption('WITH_BF_OPENAL', 'Use OpenAL if true', '')), ('BF_OPENAL', 'base path for OpenAL', ''), ('BF_OPENAL_INC', 'include path for python headers', ''), ('BF_OPENAL_LIB', 'Path to OpenAL library', ''), + ('BF_OPENAL_LIB_STATIC', 'Path to OpenAL static library', ''), ('BF_OPENAL_LIBPATH', 'Path to OpenAL library', ''), + (BoolOption('WITH_BF_STATICOPENAL', 'Staticly link to openal', 'false')), (BoolOption('WITH_BF_SDL', 'Use SDL if true', '')), ('BF_SDL', 'SDL base path', ''), @@ -171,10 +176,12 @@ def read_opts(cfg, args): # BF_FMOD = $(LCGDIR)/fmod (BoolOption('WITH_BF_OPENEXR', 'Use OPENEXR if true', 'true')), + (BoolOption('WITH_BF_STATICOPENEXR', 'Staticly link to OpenEXR', 'false')), ('BF_OPENEXR', 'OPENEXR base path', ''), ('BF_OPENEXR_INC', 'OPENEXR include path', ''), ('BF_OPENEXR_LIB', 'OPENEXR library', ''), ('BF_OPENEXR_LIBPATH', 'OPENEXR library path', ''), + ('BF_OPENEXR_LIB_STATIC', 'OPENEXR static library', ''), (BoolOption('WITH_BF_DDS', 'Use DDS if true', 'true')), From 18cda1583d8b5f2b7ebf0ea61ac262243d83723e Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 16 Sep 2008 06:33:59 +0000 Subject: [PATCH 089/125] Bugfix #17622: clicking on action IPO in outliner causes crash In some cases, no action channels existed, but yet the Outliner displayed some that, when clicked on, would cause a crash. --- source/blender/src/outliner.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/blender/src/outliner.c b/source/blender/src/outliner.c index 3f328a0cfb2..52c5592be38 100644 --- a/source/blender/src/outliner.c +++ b/source/blender/src/outliner.c @@ -1640,7 +1640,8 @@ static int tree_element_active_ipo(SpaceOops *soops, TreeElement *te, int set) if(chan->ipo) a++; } deselect_actionchannels(ob->action, 0); - select_channel(ob->action, chan, SELECT_ADD); + if (chan) + select_channel(ob->action, chan, SELECT_ADD); allqueue(REDRAWACTION, ob->ipowin); allqueue(REDRAWVIEW3D, ob->ipowin); } From 7350d71b662119b625c12babd11dc4d891dedfe5 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Tue, 16 Sep 2008 06:55:15 +0000 Subject: [PATCH 090/125] Bugfix #17630: objects are disappearing if you insert a layer key and then change time Forgot to set type of data for inserting keyframes, so data was probably written as float or so. --- source/blender/src/keyframing.c | 1 + 1 file changed, 1 insertion(+) diff --git a/source/blender/src/keyframing.c b/source/blender/src/keyframing.c index 8f887cd4756..c62032cd9d6 100644 --- a/source/blender/src/keyframing.c +++ b/source/blender/src/keyframing.c @@ -389,6 +389,7 @@ static void *get_context_ipo_poin(ID *id, int blocktype, char *actname, char *co /* init layer to be the object's layer var, then remove local view from it */ layer = ob->lay; layer &= 0xFFFFFF; + *vartype= IPO_INT_BIT; /* return pointer to this static var * - assumes that this pointer won't be stored for use later, so may not be threadsafe From 8cd673fdfb9d26f5efcb25541fc57d66284f13a5 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Tue, 16 Sep 2008 15:28:07 +0000 Subject: [PATCH 091/125] Bugfix #17633 Tiny feature: "Flip normals" in editmode also recalculates vertex normals. --- source/blender/src/editmesh_lib.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/src/editmesh_lib.c b/source/blender/src/editmesh_lib.c index 4d9679b6b8a..1aa1642d597 100644 --- a/source/blender/src/editmesh_lib.c +++ b/source/blender/src/editmesh_lib.c @@ -1906,6 +1906,7 @@ void flip_editnormals(void) { EditMesh *em = G.editMesh; EditFace *efa; + EditVert *eve; efa= em->faces.first; while(efa) { @@ -1914,6 +1915,10 @@ void flip_editnormals(void) } efa= efa->next; } + + /* update vertex normals too */ + recalc_editnormals(); + #ifdef WITH_VERSE if(G.editMesh->vnode) sync_all_versefaces_with_editfaces((VNode*)G.editMesh->vnode); From 80458f69b29685559c045b068a4383a7684df50c Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Tue, 16 Sep 2008 16:20:51 +0000 Subject: [PATCH 092/125] Added check for failing linking of a ID_PA block. --- source/blender/blenloader/intern/readfile.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index fc863ff2f5e..8865e3bb173 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2598,17 +2598,26 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part) static void lib_link_particlesystems(FileData *fd, ID *id, ListBase *particles) { - ParticleSystem *psys; + ParticleSystem *psys, *psysnext; int a; - for(psys=particles->first; psys; psys=psys->next){ + for(psys=particles->first; psys; psys=psysnext){ ParticleData *pa; + + psysnext= psys->next; + psys->part = newlibadr_us(fd, id->lib, psys->part); - psys->target_ob = newlibadr(fd, id->lib, psys->target_ob); - psys->keyed_ob = newlibadr(fd, id->lib, psys->keyed_ob); + if(psys->part) { + psys->target_ob = newlibadr(fd, id->lib, psys->target_ob); + psys->keyed_ob = newlibadr(fd, id->lib, psys->keyed_ob); - for(a=0,pa=psys->particles; atotpart; a++,pa++){ - pa->stick_ob=newlibadr(fd, id->lib, pa->stick_ob); + for(a=0,pa=psys->particles; atotpart; a++,pa++){ + pa->stick_ob=newlibadr(fd, id->lib, pa->stick_ob); + } + } + else { + BLI_remlink(particles, psys); + MEM_freeN(psys); } } } From 0922ecee93e09e0d608710a0e82258ecaba949d1 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Tue, 16 Sep 2008 18:40:54 +0000 Subject: [PATCH 093/125] "Fix" for #17636 Crashing bug - won't open a file - The cause was indeed corrupted particle settings which should have caused a deletion of the whole particle system. However the particle modifier was still left and that led to the crash. - A "fix" because there's really no way of knowing what caused the corruption of the particle settings. If anyone else gets this and can recreate I'd love to get a .blend. Now that there shouldn't be a crash anymore the symptom will be a missing particle system after file load in an object that had a particle system before. --- source/blender/blenkernel/intern/depsgraph.c | 5 ++++- source/blender/blenkernel/intern/particle.c | 2 +- source/blender/blenloader/intern/readfile.c | 9 +++++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 1be0a2aafdb..d958c43aa40 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -581,9 +581,12 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Object *ob, int for(; psys; psys=psys->next) { ParticleSettings *part= psys->part; - + dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation"); + if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE) + continue; + if(part->phystype==PART_PHYS_KEYED && psys->keyed_ob && BLI_findlink(&psys->keyed_ob->particlesystem,psys->keyed_psys-1)) { node2 = dag_get_node(dag, psys->keyed_ob); diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 2678608fb9a..c9d16c0017f 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -296,7 +296,7 @@ int psys_check_enabled(Object *ob, ParticleSystem *psys) ParticleSystemModifierData *psmd; Mesh *me; - if(psys->flag & PSYS_DISABLED) + if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE) return 0; if(ob->type == OB_MESH) { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8865e3bb173..6add88284c2 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2596,7 +2596,7 @@ static void direct_link_particlesettings(FileData *fd, ParticleSettings *part) part->pd2= newdataadr(fd, part->pd2); } -static void lib_link_particlesystems(FileData *fd, ID *id, ListBase *particles) +static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase *particles) { ParticleSystem *psys, *psysnext; int a; @@ -2616,6 +2616,11 @@ static void lib_link_particlesystems(FileData *fd, ID *id, ListBase *particles) } } else { + /* particle modifier must be removed before particle system */ + ParticleSystemModifierData *psmd= psys_get_modifier(ob,psys); + BLI_remlink(&ob->modifiers, psmd); + modifier_free((ModifierData *)psmd); + BLI_remlink(particles, psys); MEM_freeN(psys); } @@ -3069,7 +3074,7 @@ static void lib_link_object(FileData *fd, Main *main) ob->pd->tex=newlibadr_us(fd, ob->id.lib, ob->pd->tex); lib_link_scriptlink(fd, &ob->id, &ob->scriptlink); - lib_link_particlesystems(fd, &ob->id, &ob->particlesystem); + lib_link_particlesystems(fd, ob, &ob->id, &ob->particlesystem); lib_link_modifiers(fd, ob); } ob= ob->id.next; From 75685a9ca842022519b451bea14b442f69487d9a Mon Sep 17 00:00:00 2001 From: Martin Poirier Date: Tue, 16 Sep 2008 19:10:58 +0000 Subject: [PATCH 094/125] == Transform Snap == Tighten test for excluding objects as snap target. Now exclude all object that are themselves moving (that includes childs of selected objects) as well as objects with moving geometry (like hooked meshes). The previous situation would cause unfrequent bugs, but especially present in alignment cases (those concerned will understand). --- source/blender/src/transform_snap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/src/transform_snap.c b/source/blender/src/transform_snap.c index 3c17d0c1da8..8c5e1f85a3d 100644 --- a/source/blender/src/transform_snap.c +++ b/source/blender/src/transform_snap.c @@ -1173,7 +1173,7 @@ int snapObjects(int *dist, float *loc, float *no, int mode) { base= FIRSTBASE; for ( base = FIRSTBASE; base != NULL; base = base->next ) { - if ( BASE_SELECTABLE(base) && ((mode == NOT_SELECTED && (base->flag & SELECT) == 0) || (mode == NOT_ACTIVE && base != BASACT)) ) { + if ( BASE_SELECTABLE(base) && (base->flag & (BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA)) == 0 && ((mode == NOT_SELECTED && (base->flag & (SELECT|BA_WAS_SEL)) == 0) || (mode == NOT_ACTIVE && base != BASACT)) ) { Object *ob = base->object; if (ob->transflag & OB_DUPLI) From c6d0be2a9943818b98db3831e5d56969bd95c5fa Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 16 Sep 2008 19:25:35 +0000 Subject: [PATCH 095/125] Fix (harmless) error print about GameLogic.globalDict being lost. Also fixed some memory leaks in this code and simplified it. --- .../GamePlayer/ghost/GPG_Application.cpp | 29 +++++++++----- .../GamePlayer/ghost/GPG_Application.h | 23 ----------- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 18 +-------- source/gameengine/Ketsji/KX_PythonInit.cpp | 38 ++++++++++++------- 4 files changed, 44 insertions(+), 64 deletions(-) diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 580c80ee0a5..752b776beff 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -115,6 +115,7 @@ GPG_Application::GPG_Application(GHOST_ISystem* system) m_cursor(GHOST_kStandardCursorFirstCursor), m_engineInitialized(0), m_engineRunning(0), + m_isEmbedded(false), m_ketsjiengine(0), m_kxsystem(0), m_keyboard(0), @@ -128,8 +129,7 @@ GPG_Application::GPG_Application(GHOST_ISystem* system) m_blendermat(0), m_blenderglslmat(0), m_pyGlobalDictString(0), - m_pyGlobalDictString_Length(0), - m_isEmbedded(false) + m_pyGlobalDictString_Length(0) { fSystem = system; } @@ -138,6 +138,12 @@ GPG_Application::GPG_Application(GHOST_ISystem* system) GPG_Application::~GPG_Application(void) { + if(m_pyGlobalDictString) { + delete m_pyGlobalDictString; + m_pyGlobalDictString = 0; + m_pyGlobalDictString_Length = 0; + } + exitEngine(); fSystem->disposeWindow(m_mainWindow); } @@ -680,7 +686,8 @@ bool GPG_Application::startEngine(void) initPythonConstraintBinding(); initMathutils(); - /* Restore the dict */ + // Set the GameLogic.globalDict from marshal'd data, so we can + // load new blend files and keep data in GameLogic.globalDict loadGamePythonConfig(m_pyGlobalDictString, m_pyGlobalDictString_Length); m_sceneconverter->ConvertScene( @@ -718,13 +725,15 @@ bool GPG_Application::startEngine(void) void GPG_Application::stopEngine() { - // get the python dict and convert to a string for future use - char *marshal_buffer; - m_pyGlobalDictString_Length = saveGamePythonConfig(&marshal_buffer); - if (m_pyGlobalDictString_Length) { - m_pyGlobalDictString = static_cast (malloc(m_pyGlobalDictString_Length)); - memcpy(m_pyGlobalDictString, marshal_buffer, m_pyGlobalDictString_Length); - } + // GameLogic.globalDict gets converted into a buffer, and sorted in + // m_pyGlobalDictString so we can restore after python has stopped + // and started between .blend file loads. + if(m_pyGlobalDictString) { + delete m_pyGlobalDictString; + m_pyGlobalDictString = 0; + } + + m_pyGlobalDictString_Length = saveGamePythonConfig(&m_pyGlobalDictString); // when exiting the mainloop exitGamePythonScripting(); diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.h b/source/gameengine/GamePlayer/ghost/GPG_Application.h index 7fc369fc0fd..38408f919b4 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.h +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.h @@ -74,29 +74,6 @@ public: bool StartGameEngine(int stereoMode); void StopGameEngine(); - char* - GetPyGlobalDictMarshal() - { - return m_pyGlobalDictString; - }; - - void - SetPyGlobalDictMarshal( char* pyGlobalDictString, int length ) - { - if (m_pyGlobalDictString && m_pyGlobalDictString != pyGlobalDictString) - free(m_pyGlobalDictString); - - m_pyGlobalDictString = pyGlobalDictString; - m_pyGlobalDictString_Length = length; - }; - - int - GetPyGlobalDictMarshalLength() - { - return m_pyGlobalDictString_Length; - }; - - protected: bool handleWheel(GHOST_IEvent* event); bool handleButton(GHOST_IEvent* event, bool isDown); diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 8fd23318df1..01774a68cc4 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -301,8 +301,6 @@ int main(int argc, char** argv) GHOST_TUns32 fullScreenHeight= 0; int fullScreenBpp = 32; int fullScreenFrequency = 60; - char* pyGlobalDictString = NULL; /* store python dict data between blend file loading */ - int pyGlobalDictString_Length = 0; GHOST_TEmbedderWindowID parentWindow = 0; @@ -658,10 +656,6 @@ int main(int argc, char** argv) titlename = maggie->name; - // Set the GameLogic.globalDict from marshal'd data, so we can load new blend files - // abd keep data in GameLogic.globalDict - app.SetPyGlobalDictMarshal(pyGlobalDictString, pyGlobalDictString_Length); - // Check whether the game should be displayed full-screen if ((!fullScreenParFound) && (!windowParFound)) { @@ -790,12 +784,7 @@ int main(int argc, char** argv) } } app.StopGameEngine(); - - // GameLogic.globalDict has been converted into a buffer - // store in pyGlobalDictString so we can restore after python has stopped and started. - pyGlobalDictString = app.GetPyGlobalDictMarshal(); - pyGlobalDictString_Length = app.GetPyGlobalDictMarshalLength(); - + BLO_blendfiledata_free(bfd); } } while (exitcode == KX_EXIT_REQUEST_RESTART_GAME || exitcode == KX_EXIT_REQUEST_START_OTHER_GAME); @@ -814,11 +803,6 @@ int main(int argc, char** argv) free_nodesystem(); - if (pyGlobalDictString) { - free(pyGlobalDictString); - pyGlobalDictString = NULL; - } - return error ? -1 : 0; } diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 5308a0b9536..09c49a15f76 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -1393,17 +1393,21 @@ int saveGamePythonConfig( char **marshal_buffer) PyObject* pyGlobalDictMarshal = PyMarshal_WriteObjectToString( pyGlobalDict ); #endif if (pyGlobalDictMarshal) { - marshal_length= PyString_Size(pyGlobalDictMarshal); // for testing only // PyObject_Print(pyGlobalDictMarshal, stderr, 0); - *marshal_buffer = PyString_AsString(pyGlobalDictMarshal); + + marshal_length= PyString_Size(pyGlobalDictMarshal); + *marshal_buffer = new char[marshal_length + 1]; + memcpy(*marshal_buffer, PyString_AsString(pyGlobalDictMarshal), marshal_length); + + Py_DECREF(pyGlobalDictMarshal); } else { printf("Error, GameLogic.globalDict could not be marshal'd\n"); } - Py_DECREF(gameLogic); } else { printf("Error, GameLogic.globalDict was removed\n"); } + Py_DECREF(gameLogic); } else { printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); } @@ -1412,20 +1416,26 @@ int saveGamePythonConfig( char **marshal_buffer) int loadGamePythonConfig(char *marshal_buffer, int marshal_length) { - PyObject* gameLogic = PyImport_ImportModule("GameLogic"); /* Restore the dict */ if (marshal_buffer) { - PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(marshal_buffer, marshal_length); - if (pyGlobalDict) { - PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module. - return 1; + PyObject* gameLogic = PyImport_ImportModule("GameLogic"); + + if (gameLogic) { + PyObject* pyGlobalDict = PyMarshal_ReadObjectFromString(marshal_buffer, marshal_length); + + if (pyGlobalDict) { + PyDict_SetItemString(PyModule_GetDict(gameLogic), "globalDict", pyGlobalDict); // Same as importing the module. + Py_DECREF(gameLogic); + return 1; + } else { + Py_DECREF(gameLogic); + PyErr_Clear(); + printf("Error could not marshall string\n"); + } } else { - PyErr_Clear(); - printf("Error could not marshall string\n"); - } - } else { - printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); - } + printf("Error, GameLogic failed to import GameLogic.globalDict will be lost\n"); + } + } return 0; } From 99cd0dd5d5373a2437a99b69d3731043d3b014bb Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 16 Sep 2008 19:28:54 +0000 Subject: [PATCH 096/125] Fix bug that broke editing vertices through python in the game engine. --- source/gameengine/Rasterizer/RAS_MaterialBucket.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index 788af29c4bb..2b129f51609 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -107,8 +107,13 @@ RAS_MeshSlot::RAS_MeshSlot(const RAS_MeshSlot& slot) m_endindex = slot.m_endindex; for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { - *it = new RAS_DisplayArray(**it); - (*it)->m_users = 1; + // don't copy display arrays for now because it breaks python + // access to vertices, but we'll need a solution if we want to + // join display arrays for reducing draw calls. + //*it = new RAS_DisplayArray(**it); + //(*it)->m_users = 1; + + (*it)->m_users++; } } From 59414118391eb42d903b1a512374574bf3c34bb8 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Tue, 16 Sep 2008 20:52:38 +0000 Subject: [PATCH 097/125] add src/BulletSoftBody/* to cmake (other build systems also will need to do this soon) --- extern/bullet2/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/extern/bullet2/CMakeLists.txt b/extern/bullet2/CMakeLists.txt index c5495fdf92b..e28e811087f 100644 --- a/extern/bullet2/CMakeLists.txt +++ b/extern/bullet2/CMakeLists.txt @@ -35,6 +35,7 @@ FILE(GLOB SRC src/BulletDynamics/ConstraintSolver/*.cpp src/BulletDynamics/Vehicle/*.cpp src/BulletDynamics/Dynamics/*.cpp + src/BulletSoftBody/*.cpp ) ADD_DEFINITIONS(-D_LIB) From 0c77a178da71bcd5f8a83c1c951885320ba8a8d2 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Tue, 16 Sep 2008 21:09:24 +0000 Subject: [PATCH 098/125] add BulletSoftBody to SConscript and Makefile --- extern/bullet2/src/Makefile | 6 ++++-- extern/bullet2/src/SConscript | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/extern/bullet2/src/Makefile b/extern/bullet2/src/Makefile index 24f3ca9767d..8bbada24b31 100644 --- a/extern/bullet2/src/Makefile +++ b/extern/bullet2/src/Makefile @@ -38,7 +38,8 @@ BulletCollision/NarrowPhaseCollision \ BulletCollision/CollisionDispatch \ BulletDynamics/ConstraintSolver \ BulletDynamics/Vehicle \ -BulletDynamics/Dynamics +BulletDynamics/Dynamics \ +BulletSoftBody CCSRCS = $(wildcard \ LinearMath/*.cpp \ @@ -48,7 +49,8 @@ BulletCollision/NarrowPhaseCollision/*.cpp \ BulletCollision/CollisionDispatch/*.cpp \ BulletDynamics/ConstraintSolver/*.cpp \ BulletDynamics/Vehicle/*.cpp \ -BulletDynamics/Dynamics/*.cpp) +BulletDynamics/Dynamics/*.cpp \ +BulletSoftBody/*.cpp) CPPFLAGS += -D_LIB -I. -IBulletCollision -IBulletDynamics -ILinearMath diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript index 59b823982f5..c2980a0d737 100644 --- a/extern/bullet2/src/SConscript +++ b/extern/bullet2/src/SConscript @@ -23,7 +23,7 @@ elif sys.platform=='darwin': linearmath_src = env.Glob("LinearMath/*.cpp") -bulletdyn_src = env.Glob("BulletDynamics/Vehicle/*.cpp") + env.Glob("BulletDynamics/ConstraintSolver/*.cpp") + env.Glob("BulletDynamics/Dynamics/*.cpp") +bulletdyn_src = env.Glob("BulletSoftBody/*.cpp") + 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/CollisionShapes/*.cpp") + env.Glob("BulletCollision/NarrowPhaseCollision/*.cpp") From 73fd8000775e1558b5140ace86860477d61d8b98 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 16 Sep 2008 21:11:38 +0000 Subject: [PATCH 099/125] Fix for bug #5413: game engine armature actions and shapes keys didn't work correct with scene suspend/resume, now works the same as IPO's. --- source/gameengine/Converter/BL_ActionActuator.cpp | 2 ++ source/gameengine/Converter/BL_ShapeActionActuator.cpp | 2 ++ source/gameengine/Ketsji/KX_IpoActuator.cpp | 7 ++++--- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index 119465c8726..b8514e33127 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -152,6 +152,8 @@ bool BL_ActionActuator::Update(double curtime, bool frame) bool apply=true; int priority; float newweight; + + curtime -= KX_KetsjiEngine::GetSuspendedDelta(); // result = true if animation has to be continued, false if animation stops // maybe there are events for us in the queue ! diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index 679b0df7ec6..da5ca1e7c95 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -155,6 +155,8 @@ bool BL_ShapeActionActuator::Update(double curtime, bool frame) bool apply=true; int priority; float newweight; + + curtime -= KX_KetsjiEngine::GetSuspendedDelta(); // result = true if animation has to be continued, false if animation stops // maybe there are events for us in the queue ! diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp index a203ea6a6ff..75e4ade6574 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.cpp +++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp @@ -130,7 +130,6 @@ void KX_IpoActuator::SetStartTime(float curtime) { float direction = m_startframe < m_endframe ? 1.0f : -1.0f; - curtime = curtime - KX_KetsjiEngine::GetSuspendedDelta(); if (m_direction > 0) m_starttime = curtime - direction*(m_localtime - m_startframe)/KX_KetsjiEngine::GetAnimFrameRate(); else @@ -139,7 +138,7 @@ void KX_IpoActuator::SetStartTime(float curtime) void KX_IpoActuator::SetLocalTime(float curtime) { - float delta_time = ((curtime - m_starttime) - KX_KetsjiEngine::GetSuspendedDelta())*KX_KetsjiEngine::GetAnimFrameRate(); + float delta_time = (curtime - m_starttime)*KX_KetsjiEngine::GetAnimFrameRate(); // negative delta_time is caused by floating point inaccuracy // perhaps the inaccuracy could be reduced a bit @@ -165,6 +164,8 @@ bool KX_IpoActuator::Update(double curtime, bool frame) int numevents = 0; bool bIpoStart = false; + curtime -= KX_KetsjiEngine::GetSuspendedDelta(); + if (frame) { numevents = m_events.size(); @@ -180,7 +181,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame) if (m_starttime < -2.0f*start_smaller_then_end*(m_endframe - m_startframe)) { // start for all Ipo, initial start for LOOP_STOP - m_starttime = curtime - KX_KetsjiEngine::GetSuspendedDelta(); + m_starttime = curtime; m_bIpoPlaying = true; bIpoStart = true; } From 0cae8151271652b714219c776da342726d78b9d4 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Tue, 16 Sep 2008 21:16:32 +0000 Subject: [PATCH 100/125] Fix for [#17561] when i try to change the particle to hair I cant choose group or object as viz. -Partly reverted Genscher's previous fix on the issue and added the idea he had as a special case --- source/blender/blenkernel/intern/particle.c | 26 +++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index c9d16c0017f..33af6037519 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3850,7 +3850,7 @@ void psys_get_dupli_texture(Object *ob, ParticleSettings *part, ParticleSystemMo void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale) { - float loc[3], nor[3], vec[3], len, obrotmat[4][4], qmat[4][4]; + float loc[3], nor[3], vec[3], side[3], len, obrotmat[4][4], qmat[4][4]; float xvec[3] = {-1.0, 0.0, 0.0}, q[4]; VecSubf(vec, (cache+cache->steps-1)->co, cache->co); @@ -3875,9 +3875,27 @@ void psys_get_dupli_path_transform(Object *ob, ParticleSystem *psys, ParticleSys Mat4MulMat4(mat, obrotmat, qmat); } else { - Normalize(nor); - Mat4One(mat); - VECCOPY(mat[2], nor); // mat[2] is normal/direction + /* make sure that we get a proper side vector */ + if(fabs(Inpf(nor,vec))>0.999999) { + if(fabs(Inpf(nor,xvec))>0.999999) { + nor[0] = 0.0f; + nor[1] = 1.0f; + nor[2] = 0.0f; + } + else { + nor[0] = 1.0f; + nor[1] = 0.0f; + nor[2] = 0.0f; + } + } + Crossf(side, nor, vec); + Normalize(side); + Crossf(nor, vec, side); + + Mat4One(mat); + VECCOPY(mat[0], vec); + VECCOPY(mat[1], side); + VECCOPY(mat[2], nor); } *scale= len; From 73c8d76ba406a7753b8b6aaa1e304d9e311f816a Mon Sep 17 00:00:00 2001 From: Nathan Letwory Date: Tue, 16 Sep 2008 21:23:56 +0000 Subject: [PATCH 101/125] * make BulletSoftBody own small lib to make sure bullet libs don't grow too large for our beloved scons/mingw users. --- extern/bullet2/src/SConscript | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript index c2980a0d737..b2ec67984d3 100644 --- a/extern/bullet2/src/SConscript +++ b/extern/bullet2/src/SConscript @@ -23,13 +23,16 @@ elif sys.platform=='darwin': linearmath_src = env.Glob("LinearMath/*.cpp") -bulletdyn_src = env.Glob("BulletSoftBody/*.cpp") + env.Glob("BulletDynamics/Vehicle/*.cpp") + env.Glob("BulletDynamics/ConstraintSolver/*.cpp") + env.Glob("BulletDynamics/Dynamics/*.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/CollisionShapes/*.cpp") + env.Glob("BulletCollision/NarrowPhaseCollision/*.cpp") -incs = '. BulletCollision BulletDynamics LinearMath' +softbody_src = env.Glob("BulletSoftBody/*.cpp") + +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_bullet2softbody', sources=softbody_src, includes=Split(incs), defines=Split(defs), libtype=['game2', 'player'], priority=[20,170], compileflags=cflags ) From 9b7d40dbae1be5aa18894ffbc8f97a4a8c4c6fdd Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Tue, 16 Sep 2008 22:52:42 +0000 Subject: [PATCH 102/125] BGE patch: bullet buttons UI change after discussion with Erwin: use a drop down instead of a series of buttons. Introduction of soft body option. --- source/blender/blenkernel/intern/object.c | 2 +- source/blender/blenloader/intern/readfile.c | 2 +- source/blender/makesdna/DNA_object_types.h | 13 +- source/blender/python/api2_2x/Object.c | 6 +- source/blender/src/buttons_logic.c | 120 ++++++++++++------ .../Converter/BL_BlenderDataConversion.cpp | 2 +- 6 files changed, 100 insertions(+), 45 deletions(-) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index e63d6047cc6..6cbcba65f56 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -960,7 +960,7 @@ Object *add_only_object(int type, char *name) ob->anisotropicFriction[0] = 1.0f; ob->anisotropicFriction[1] = 1.0f; ob->anisotropicFriction[2] = 1.0f; - ob->gameflag= OB_PROP|OB_PHYSICS; + ob->gameflag= OB_PROP|OB_COLLISION; ob->margin = 0.0; /* NT fluid sim defaults */ diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 6add88284c2..f3f1a99cdbf 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -7794,7 +7794,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) if (main->versionfile < 247 || (main->versionfile == 247 && main->subversionfile < 2)){ Object *ob; for(ob = main->object.first; ob; ob= ob->id.next) { - ob->gameflag |= OB_PHYSICS; + ob->gameflag |= OB_COLLISION; ob->margin = 0.06; } } diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 3708db3fd38..66bdaf2c98b 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -212,7 +212,8 @@ typedef struct Object { short shapenr, shapeflag; /* current shape key for menu or pinned, flag for pinning */ float smoothresh; /* smoothresh is phong interpolation ray_shadow correction in render */ - short recalco, pad4; /* recalco for temp storage of ob->recalc, bad design warning */ + short recalco; /* recalco for temp storage of ob->recalc, bad design warning */ + short body_type; /* for now used to temporarily holds the type of collision object */ struct FluidsimSettings *fluidsimSettings; /* if fluidsim enabled, store additional settings */ @@ -429,13 +430,21 @@ extern Object workob; #define OB_PROP 16384 #define OB_MAINACTOR 32768 -#define OB_PHYSICS 65536 +#define OB_COLLISION 65536 +#define OB_SOFT_BODY 0x20000 /* ob->gameflag2 */ #define OB_NEVER_DO_ACTIVITY_CULLING 1 #define OB_LIFE (OB_PROP|OB_DYNAMIC|OB_ACTOR|OB_MAINACTOR|OB_CHILD) +/* ob->body_type */ +#define OB_BODY_TYPE_NO_COLLISION 0 +#define OB_BODY_TYPE_STATIC 1 +#define OB_BODY_TYPE_DYNAMIC 2 +#define OB_BODY_TYPE_RIGID 3 +#define OB_BODY_TYPE_SOFT 4 + /* ob->scavisflag */ #define OB_VIS_SENS 1 #define OB_VIS_CONT 2 diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index 45d6bfa3c01..0d5af06377c 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -3519,8 +3519,8 @@ static int Object_setRBMass( BPy_Object * self, PyObject * args ) /* this is too low level, possible to add helper methods */ -#define GAMEFLAG_MASK ( OB_DYNAMIC | OB_CHILD | OB_ACTOR | OB_DO_FH | \ - OB_ROT_FH | OB_ANISOTROPIC_FRICTION | OB_GHOST | OB_RIGID_BODY | \ +#define GAMEFLAG_MASK ( OB_COLLISION | OB_DYNAMIC | OB_CHILD | OB_ACTOR | OB_DO_FH | \ + OB_ROT_FH | OB_ANISOTROPIC_FRICTION | OB_GHOST | OB_RIGID_BODY | OB_SOFT_BODY | \ OB_BOUNDS | OB_COLLISION_RESPONSE | OB_SECTOR | OB_PROP | \ OB_MAINACTOR ) @@ -5497,6 +5497,7 @@ static PyObject *M_Object_RBFlagsDict( void ) if( M ) { BPy_constant *d = ( BPy_constant * ) M; + PyConstant_Insert( d, "COLLISION", PyInt_FromLong( OB_COLLISION ) ); PyConstant_Insert( d, "DYNAMIC", PyInt_FromLong( OB_DYNAMIC ) ); PyConstant_Insert( d, "CHILD", PyInt_FromLong( OB_CHILD ) ); PyConstant_Insert( d, "ACTOR", PyInt_FromLong( OB_ACTOR ) ); @@ -5506,6 +5507,7 @@ static PyObject *M_Object_RBFlagsDict( void ) PyInt_FromLong( OB_ANISOTROPIC_FRICTION ) ); PyConstant_Insert( d, "GHOST", PyInt_FromLong( OB_GHOST ) ); PyConstant_Insert( d, "RIGIDBODY", PyInt_FromLong( OB_RIGID_BODY ) ); + PyConstant_Insert( d, "SOFTBODY", PyInt_FromLong( OB_SOFT_BODY ) ); PyConstant_Insert( d, "BOUNDS", PyInt_FromLong( OB_BOUNDS ) ); PyConstant_Insert( d, "COLLISION_RESPONSE", PyInt_FromLong( OB_COLLISION_RESPONSE ) ); diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 5a689050ff0..e16443460a1 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -2849,10 +2849,10 @@ void buttons_enji(uiBlock *block, Object *ob) void buttons_ketsji(uiBlock *block, Object *ob) { - uiDefButBitI(block, TOG, OB_PHYSICS, B_REDR, "Physics", + uiDefButBitI(block, TOG, OB_COLLISION, B_REDR, "Physics", 10,205,70,19, &ob->gameflag, 0, 0, 0, 0, "Objects that have a physics representation"); - if (ob->gameflag & OB_PHYSICS) { + if (ob->gameflag & OB_COLLISION) { uiBlockBeginAlign(block); uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", 80,205,55,19, &ob->gameflag, 0, 0, 0, 0, @@ -2933,46 +2933,90 @@ void buttons_ketsji(uiBlock *block, Object *ob) } } +static void check_actor(void *arg1_but, void *arg2_object) +{ + int *gameflag = arg2_object; + /* force enabled ACTOR for body >= dynamic */ + if (*gameflag & OB_DYNAMIC) + *gameflag |= OB_ACTOR; +} + +static void check_body_type(void *arg1_but, void *arg2_object) +{ + Object *ob = arg2_object; + + switch (ob->body_type) { + case OB_BODY_TYPE_NO_COLLISION: + ob->gameflag &= ~OB_COLLISION; + break; + case OB_BODY_TYPE_STATIC: + ob->gameflag |= OB_COLLISION; + ob->gameflag &= ~(OB_DYNAMIC|OB_RIGID_BODY|OB_SOFT_BODY); + break; + case OB_BODY_TYPE_DYNAMIC: + ob->gameflag |= OB_COLLISION|OB_DYNAMIC|OB_ACTOR; + ob->gameflag &= ~(OB_RIGID_BODY|OB_SOFT_BODY); + break; + case OB_BODY_TYPE_RIGID: + ob->gameflag |= OB_COLLISION|OB_DYNAMIC|OB_RIGID_BODY|OB_ACTOR; + ob->gameflag &= ~(OB_SOFT_BODY); + break; + default: + case OB_BODY_TYPE_SOFT: + ob->gameflag |= OB_COLLISION|OB_DYNAMIC|OB_SOFT_BODY|OB_ACTOR; + ob->gameflag &= ~(OB_RIGID_BODY); + break; + } +} + void buttons_bullet(uiBlock *block, Object *ob) { - uiDefButBitI(block, TOG, OB_PHYSICS, B_REDR, "Physics", - 10,205,70,19, &ob->gameflag, 0, 0, 0, 0, - "Objects that have a physics representation"); - if (ob->gameflag & OB_PHYSICS) { - uiBlockBeginAlign(block); - uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", - 80,205,55,19, &ob->gameflag, 0, 0, 0, 0, + uiBut *but; + + /* determine the body_type setting based on flags */ + if (!(ob->gameflag & OB_COLLISION)) + ob->body_type = OB_BODY_TYPE_NO_COLLISION; + else if (!(ob->gameflag & OB_DYNAMIC) || !(ob->gameflag & OB_DYNAMIC)) + ob->body_type = OB_BODY_TYPE_STATIC; + else if (!(ob->gameflag & (OB_RIGID_BODY|OB_SOFT_BODY))) + ob->body_type = OB_BODY_TYPE_DYNAMIC; + else if (ob->gameflag & OB_RIGID_BODY) + ob->body_type = OB_BODY_TYPE_RIGID; + else + ob->body_type = OB_BODY_TYPE_SOFT; + + uiBlockBeginAlign(block); + but = uiDefButS(block, MENU, REDRAWVIEW3D, + "Object type%t|No collision%x0|Static%x1|Dynamic%x2|Rigid body%x3|Soft body%x4", + 10, 205, 150, 19, &ob->body_type, 0, 0, 0, 0, "Selects the type of physical representation of the object"); + uiButSetFunc(but, check_body_type, but, ob); + + if (ob->gameflag & OB_COLLISION) { + but = uiDefButBitI(block, TOG, OB_ACTOR, B_REDR, "Actor", + 160,205,55,19, &ob->gameflag, 0, 0, 0, 0, "Objects that are detected by the Near and Radar sensor"); - if(ob->gameflag & OB_ACTOR) { - uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 135,205,55,19, - &ob->gameflag, 0, 0, 0, 0, - "Objects that don't restitute collisions (like a ghost)"); - uiDefButBitI(block, TOG, OB_DYNAMIC, B_REDR, "Dynamic", 190,205,75,19, - &ob->gameflag, 0, 0, 0, 0, - "Motion defined by laws of physics"); + uiButSetFunc(but, check_actor, but, &ob->gameflag); - if(ob->gameflag & OB_DYNAMIC) { - uiDefButBitI(block, TOG, OB_RIGID_BODY, B_REDR, "Rigid Body", 265,205,85,19, - &ob->gameflag, 0, 0, 0, 0, - "Enable rolling physics"); + uiDefButBitI(block, TOG, OB_GHOST, B_REDR, "Ghost", 215,205,55,19, + &ob->gameflag, 0, 0, 0, 0, + "Objects that don't restitute collisions (like a ghost)"); + if(ob->gameflag & OB_DYNAMIC) { + uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,205,80,19, + &ob->gameflag, 0, 0, 0, 0, + "Disable auto (de)activation"); + uiDefButF(block, NUM, B_DIFF, "Mass:", 10, 185, 170, 19, + &ob->mass, 0.01, 10000.0, 10, 2, + "The mass of the Object"); + uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 180, 185, 170, 19, + &ob->inertia, 0.01, 10.0, 10, 2, + "Bounding sphere radius, not used for other bounding shapes"); - uiDefButF(block, NUM, B_DIFF, "Mass:", 10, 185, 130, 19, - &ob->mass, 0.01, 10000.0, 10, 2, - "The mass of the Object"); - uiDefButF(block, NUM, REDRAWVIEW3D, "Radius:", 140, 185, 130, 19, - &ob->inertia, 0.01, 10.0, 10, 2, - "Bounding sphere radius, not used for other bounding shapes"); - uiDefButBitI(block, TOG, OB_COLLISION_RESPONSE, B_REDR, "No sleeping", 270,185,80,19, - &ob->gameflag, 0, 0, 0, 0, - "Disable auto (de)activation"); - - uiDefButF(block, NUMSLI, B_DIFF, "Damp ", 10, 165, 150, 19, - &ob->damping, 0.0, 1.0, 10, 0, - "General movement damping"); - uiDefButF(block, NUMSLI, B_DIFF, "RotDamp ", 160, 165, 190, 19, - &ob->rdamping, 0.0, 1.0, 10, 0, - "General rotation damping"); - } + uiDefButF(block, NUMSLI, B_DIFF, "Damp ", 10, 165, 150, 19, + &ob->damping, 0.0, 1.0, 10, 0, + "General movement damping"); + uiDefButF(block, NUMSLI, B_DIFF, "RotDamp ", 160, 165, 190, 19, + &ob->rdamping, 0.0, 1.0, 10, 0, + "General rotation damping"); } uiBlockEndAlign(block); @@ -2999,8 +3043,8 @@ void buttons_bullet(uiBlock *block, Object *ob) &ob->gameflag, 0, 0, 0, 0, "Add Children"); } - uiBlockEndAlign(block); } + uiBlockEndAlign(block); } static void check_controller_state_mask(void *arg1_but, void *arg2_mask) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 8bdec219354..c3992d02eee 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -1280,7 +1280,7 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, //bool bRigidBody = (userigidbody == 0); // object has physics representation? - if (!(blenderobject->gameflag & OB_PHYSICS)) + if (!(blenderobject->gameflag & OB_COLLISION)) return; // get Root Parent of blenderobject From 9064ed8d6aa934dedc4b344e328566a8549371f6 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 17 Sep 2008 01:29:54 +0000 Subject: [PATCH 103/125] Fix for bug #4192: game engine armatures that are dynamically added but don't have an action got the pose of already added armatures, even though they're not related. This also fixes an issue where the armature in Blender would end up in the pose from the game after ESC, removes unneeded copies made during armature evaluation, and also solves the constraint copying hack. --- source/blender/blenkernel/BKE_action.h | 4 ++ source/blender/blenkernel/intern/action.c | 55 +++++++++++++++++ .../Converter/BL_ActionActuator.cpp | 6 +- .../Converter/BL_ArmatureObject.cpp | 59 ++++++++----------- .../gameengine/Converter/BL_ArmatureObject.h | 3 +- .../gameengine/Converter/BL_ShapeDeformer.cpp | 4 ++ .../gameengine/Converter/BL_SkinDeformer.cpp | 2 + .../GamePlayer/ghost/GPG_Application.cpp | 4 +- 8 files changed, 95 insertions(+), 42 deletions(-) diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 4a13fa31f6c..37ced4cb00b 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -163,6 +163,10 @@ void extract_ipochannels_from_action(ListBase *lb, struct ID *id, struct bAction /* write values returned by extract_ipochannels_from_action, returns the number of value written */ int execute_ipochannels(ListBase *lb); +/* functions used by the game engine */ +void game_copy_pose(struct bPose **dst, struct bPose *src); +void game_free_pose(struct bPose *pose); + #ifdef __cplusplus }; #endif diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 043ede5987a..d65a99f23f0 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -62,6 +62,7 @@ #include "BLI_arithb.h" #include "BLI_blenlib.h" +#include "BLI_ghash.h" #include "nla.h" @@ -340,6 +341,60 @@ void free_pose(bPose *pose) } } +void game_copy_pose(bPose **dst, bPose *src) +{ + bPose *out; + bPoseChannel *pchan, *outpchan; + GHash *ghash; + + /* the game engine copies the current armature pose and then swaps + * the object pose pointer. this makes it possible to change poses + * without affecting the original blender data. */ + + if (!src) { + *dst=NULL; + return; + } + else if (*dst==src) { + printf("copy_pose source and target are the same\n"); + *dst=NULL; + return; + } + + out= MEM_dupallocN(src); + out->agroups.first= out->agroups.last= NULL; + duplicatelist(&out->chanbase, &src->chanbase); + + /* remap pointers */ + ghash= BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp); + + pchan= src->chanbase.first; + outpchan= out->chanbase.first; + for (; pchan; pchan=pchan->next, outpchan=outpchan->next) + BLI_ghash_insert(ghash, pchan, outpchan); + + for (pchan=out->chanbase.first; pchan; pchan=pchan->next) { + pchan->parent= BLI_ghash_lookup(ghash, pchan->parent); + pchan->child= BLI_ghash_lookup(ghash, pchan->child); + pchan->path= NULL; + } + + BLI_ghash_free(ghash, NULL, NULL); + + *dst=out; +} + +void game_free_pose(bPose *pose) +{ + if (pose) { + /* we don't free constraints, those are owned by the original pose */ + if(pose->chanbase.first) + BLI_freelistN(&pose->chanbase); + + MEM_freeN(pose); + } +} + static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan) { bConstraint *pcon, *con; diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index b8514e33127..c08427c6d27 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -59,11 +59,11 @@ BL_ActionActuator::~BL_ActionActuator() { if (m_pose) - free_pose(m_pose); + game_free_pose(m_pose); if (m_userpose) - free_pose(m_userpose); + game_free_pose(m_userpose); if (m_blendpose) - free_pose(m_blendpose); + game_free_pose(m_blendpose); } void BL_ActionActuator::ProcessReplica(){ diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index bf774bf7568..d2001212f7d 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -45,7 +45,6 @@ #include #endif - BL_ArmatureObject::BL_ArmatureObject( void* sgReplicationInfo, SG_Callbacks callbacks, @@ -65,7 +64,7 @@ BL_ArmatureObject::BL_ArmatureObject( * the original pose before calling into blender functions, to deal with * replica's or other objects using the same blender object */ m_pose = NULL; - copy_pose(&m_pose, m_objArma->pose, 1 /* copy_constraint_channels_hack */); + game_copy_pose(&m_pose, m_objArma->pose); } CValue* BL_ArmatureObject::GetReplica() @@ -84,32 +83,30 @@ void BL_ArmatureObject::ProcessReplica(BL_ArmatureObject *replica) KX_GameObject::ProcessReplica(replica); replica->m_pose = NULL; - copy_pose(&replica->m_pose, m_pose, 1 /* copy_constraint_channels_hack */); + game_copy_pose(&replica->m_pose, m_pose); } BL_ArmatureObject::~BL_ArmatureObject() { if (m_pose) - free_pose(m_pose); -} - -bool BL_ArmatureObject::VerifyPose() -{ - if(m_lastapplyframe != m_lastframe) { - extract_pose_from_pose(m_objArma->pose, m_pose); - where_is_pose(m_objArma); - m_lastapplyframe = m_lastframe; - extract_pose_from_pose(m_pose, m_objArma->pose); - return false; - } - else - return true; + game_free_pose(m_pose); } void BL_ArmatureObject::ApplyPose() { - if(VerifyPose()) - extract_pose_from_pose(m_objArma->pose, m_pose); + m_armpose = m_objArma->pose; + m_objArma->pose = m_pose; + + if(m_lastapplyframe != m_lastframe) { + where_is_pose(m_objArma); + m_lastapplyframe = m_lastframe; + } +} + +void BL_ArmatureObject::RestorePose() +{ + m_objArma->pose = m_armpose; + m_armpose = NULL; } void BL_ArmatureObject::SetPose(bPose *pose) @@ -164,8 +161,7 @@ void BL_ArmatureObject::GetPose(bPose **pose) a crash and memory leakage when &BL_ActionActuator::m_pose is freed */ - int copy_constraint_channels_hack = 1; - copy_pose(pose, m_pose, copy_constraint_channels_hack); + game_copy_pose(pose, m_pose); } else { if (*pose == m_pose) @@ -181,17 +177,10 @@ void BL_ArmatureObject::GetMRDPose(bPose **pose) /* If the caller supplies a null pose, create a new one. */ /* Otherwise, copy the armature's pose channels into the caller-supplied pose */ - if (!*pose) { - // must duplicate the constraints too otherwise we have corruption in free_pose_channels() - // because it will free the blender constraints. - // Ideally, blender should rememeber that the constraints were not copied so that - // free_pose_channels() would not free them. - copy_pose(pose, m_pose, 1); - } - else { + if (!*pose) + game_copy_pose(pose, m_pose); + else extract_pose_from_pose(*pose, m_pose); - } - } short BL_ArmatureObject::GetActivePriority() @@ -210,13 +199,11 @@ bool BL_ArmatureObject::GetBoneMatrix(Bone* bone, MT_Matrix4x4& matrix) ApplyPose(); pchan = get_pose_channel(m_objArma->pose, bone->name); - - if(pchan) { + if(pchan) matrix.setValue(&pchan->pose_mat[0][0]); - return true; - } + RestorePose(); - return false; + return (pchan != NULL); } float BL_ArmatureObject::GetBoneLength(Bone* bone) const diff --git a/source/gameengine/Converter/BL_ArmatureObject.h b/source/gameengine/Converter/BL_ArmatureObject.h index 6f2c0d2f4c9..d68e37d9e37 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.h +++ b/source/gameengine/Converter/BL_ArmatureObject.h @@ -61,7 +61,7 @@ public: void SetPose (struct bPose *pose); void ApplyPose(); - bool VerifyPose(); + void RestorePose(); bool SetActiveAction(class BL_ActionActuator *act, short priority, double curtime); @@ -82,6 +82,7 @@ protected: Object *m_objArma; struct bArmature *m_armature; struct bPose *m_pose; + struct bPose *m_armpose; struct bPose *m_framePose; double m_lastframe; class BL_ActionActuator *m_activeAct; diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp index 236cd1a6667..dfd33e45fef 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.cpp +++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp @@ -109,6 +109,7 @@ bool BL_ShapeDeformer::ExecuteShapeDrivers(void) vector::iterator it; void *poin; int type; + // the shape drivers use the bone matrix as input. Must // update the matrix now m_armobj->ApplyPose(); @@ -121,7 +122,10 @@ bool BL_ShapeDeformer::ExecuteShapeDrivers(void) if (poin) write_ipo_poin(poin, type, icu->curval); } + ForceUpdate(); + m_armobj->RestorePose(); + return true; } return false; diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index d8e7a9cdadf..b7b39ad7fbf 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -197,6 +197,8 @@ bool BL_SkinDeformer::Update(void) /* Update the current frame */ m_lastArmaUpdate=m_armobj->GetLastFrame(); + m_armobj->RestorePose(); + /* indicate that the m_transverts and normals are up to date */ return true; } diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 752b776beff..4cd5184fee1 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -139,7 +139,7 @@ GPG_Application::GPG_Application(GHOST_ISystem* system) GPG_Application::~GPG_Application(void) { if(m_pyGlobalDictString) { - delete m_pyGlobalDictString; + delete [] m_pyGlobalDictString; m_pyGlobalDictString = 0; m_pyGlobalDictString_Length = 0; } @@ -729,7 +729,7 @@ void GPG_Application::stopEngine() // m_pyGlobalDictString so we can restore after python has stopped // and started between .blend file loads. if(m_pyGlobalDictString) { - delete m_pyGlobalDictString; + delete [] m_pyGlobalDictString; m_pyGlobalDictString = 0; } From ae418491dcbfa5c7e7415523695bdaea78a0b03e Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Wed, 17 Sep 2008 01:49:47 +0000 Subject: [PATCH 104/125] Preparation for real-time soft bodies for the game engine, step 1 out of 3. This should be harmless/non-intrusive. Please make sure each build system include extern/bullet2/src/BulletSoftBody/* and extern/bullet2/src/LinearMath/btConvexHull.* --- .../CollisionDispatch/btCollisionObject.h | 9 + .../Physics/Bullet/CcdPhysicsController.cpp | 377 ++++++++++++------ .../Physics/Bullet/CcdPhysicsController.h | 16 +- .../Physics/Bullet/CcdPhysicsEnvironment.cpp | 148 ++++--- .../Physics/Bullet/CcdPhysicsEnvironment.h | 4 +- 5 files changed, 382 insertions(+), 172 deletions(-) diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h index eb297ef4a3b..7ef3787b3ac 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCollisionObject.h @@ -268,6 +268,15 @@ public: m_interpolationWorldTransform = trans; } + void setInterpolationLinearVelocity(const btVector3& linvel) + { + m_interpolationLinearVelocity = linvel; + } + + void setInterpolationAngularVelocity(const btVector3& angvel) + { + m_interpolationAngularVelocity = angvel; + } const btVector3& getInterpolationLinearVelocity() const { diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 8ba138df437..b1b97b5370f 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -19,6 +19,7 @@ subject to the following restrictions: #include "PHY_IMotionState.h" #include "CcdPhysicsEnvironment.h" #include "RAS_MeshObject.h" +#include "BulletSoftBody/btSoftBody.h" class BP_Proxy; @@ -63,11 +64,11 @@ CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci) CreateRigidbody(); - - #ifdef WIN32 - if (m_body->getInvMass()) - m_body->setLinearVelocity(startVel); - #endif +///??? +#ifdef WIN32 + if (GetRigidBody() && !GetRigidBody()->isStaticObject()) + GetRigidBody()->setLinearVelocity(startVel); +#endif } @@ -119,20 +120,59 @@ public: }; +btRigidBody* CcdPhysicsController::GetRigidBody() +{ + return btRigidBody::upcast(m_object); +} +btCollisionObject* CcdPhysicsController::GetCollisionObject() +{ + return m_object; +} +btSoftBody* CcdPhysicsController::GetSoftBody() +{ + return btSoftBody::upcast(m_object); +} + + void CcdPhysicsController::CreateRigidbody() { btTransform trans = GetTransformFromMotionState(m_MotionState); - m_bulletMotionState = new BlenderBulletMotionState(m_MotionState); - 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; - rbci.m_angularDamping = m_cci.m_angularDamping; - rbci.m_friction = m_cci.m_friction; - rbci.m_restitution = m_cci.m_restitution; - - m_body = new btRigidBody(rbci); + ///either create a btCollisionObject, btRigidBody or btSoftBody + + //create a collision object + if (0)//m_cci.m_mass==0.f) + { + 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; + rbci.m_angularDamping = m_cci.m_angularDamping; + rbci.m_friction = m_cci.m_friction; + rbci.m_restitution = m_cci.m_restitution; + m_object = new btCollisionObject(); + m_object->setCollisionShape(rbci.m_collisionShape); + btTransform startTrans; + + if (rbci.m_motionState) + { + rbci.m_motionState->getWorldTransform(startTrans); + } else + { + startTrans = rbci.m_startWorldTransform; + } + m_object->setWorldTransform(startTrans); + m_object->setInterpolationWorldTransform(startTrans); + + } else + { + 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; + rbci.m_angularDamping = m_cci.m_angularDamping; + rbci.m_friction = m_cci.m_friction; + rbci.m_restitution = m_cci.m_restitution; + m_object = new btRigidBody(rbci); + } // // init the rigidbody properly @@ -145,15 +185,20 @@ void CcdPhysicsController::CreateRigidbody() if ((m_cci.m_collisionFilterGroup & CcdConstructionInfo::SensorFilter) != 0) { // reset the flags that have been set so far - m_body->setCollisionFlags(0); + GetCollisionObject()->setCollisionFlags(0); } - m_body->setCollisionFlags(m_body->getCollisionFlags() | m_cci.m_collisionFlags); - m_body->setGravity( m_cci.m_gravity); - m_body->setDamping(m_cci.m_linearDamping, m_cci.m_angularDamping); + GetCollisionObject()->setCollisionFlags(m_object->getCollisionFlags() | m_cci.m_collisionFlags); + btRigidBody* body = GetRigidBody(); - if (!m_cci.m_bRigid) + if (body) { - m_body->setAngularFactor(0.f); + body->setGravity( m_cci.m_gravity); + body->setDamping(m_cci.m_linearDamping, m_cci.m_angularDamping); + + if (!m_cci.m_bRigid) + { + body->setAngularFactor(0.f); + } } } @@ -180,7 +225,7 @@ CcdPhysicsController::~CcdPhysicsController() delete m_MotionState; if (m_bulletMotionState) delete m_bulletMotionState; - delete m_body; + delete m_object; if (m_collisionShape) { @@ -212,12 +257,14 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time) { //sync non-static to motionstate, and static from motionstate (todo: add kinematic etc.) - if (!m_body->isStaticObject()) + btRigidBody* body = GetRigidBody(); + + if (body && !body->isStaticObject()) { - const btVector3& worldPos = m_body->getCenterOfMassPosition(); + const btVector3& worldPos = body->getCenterOfMassPosition(); m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]); - const btQuaternion& worldquat = m_body->getOrientation(); + const btQuaternion& worldquat = body->getOrientation(); m_MotionState->setWorldOrientation(worldquat[0],worldquat[1],worldquat[2],worldquat[3]); m_MotionState->calculateWorldTransformations(); @@ -236,7 +283,7 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time) btTransform oldTrans = m_body->getCenterOfMassTransform(); btTransform newTrans(worldquat,worldPos); - m_body->setCenterOfMassTransform(newTrans); + SetCenterOfMassTransform(newTrans); //need to keep track of previous position for friction effects... m_MotionState->calculateWorldTransformations(); @@ -285,15 +332,17 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta } } - m_body = 0; + m_object = 0; CreateRigidbody(); - if (m_body) + btRigidBody* body = GetRigidBody(); + + if (body) { if (m_cci.m_mass) { - m_body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); - } + body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); + } } m_cci.m_physicsEnv->addCcdPhysicsController(this); @@ -328,42 +377,77 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta +} + + +void CcdPhysicsController::SetCenterOfMassTransform(btTransform& xform) +{ + btRigidBody* body = GetRigidBody(); + if (body) + { + body->setCenterOfMassTransform(xform); + } else + { + //either collision object or soft body? + if (GetSoftBody()) + { + //not yet + } else + { + + if (m_object->isStaticOrKinematicObject()) + { + m_object->setInterpolationWorldTransform(m_object->getWorldTransform()); + } else + { + m_object->setInterpolationWorldTransform(xform); + } + if (body) + { + body->setInterpolationLinearVelocity(body->getLinearVelocity()); + body->setInterpolationAngularVelocity(body->getAngularVelocity()); + body->updateInertiaTensor(); + } + m_object->setWorldTransform(xform); + } + } } // kinematic methods void CcdPhysicsController::RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local) { - if (m_body) + if (m_object) { - m_body->activate(true); - if (m_body->isStaticObject()) + m_object->activate(true); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } + btRigidBody* body = GetRigidBody(); btVector3 dloc(dlocX,dlocY,dlocZ); - btTransform xform = m_body->getCenterOfMassTransform(); - + btTransform xform = m_object->getWorldTransform(); + if (local) { dloc = xform.getBasis()*dloc; } xform.setOrigin(xform.getOrigin() + dloc); - m_body->setCenterOfMassTransform(xform); + SetCenterOfMassTransform(xform); } } void CcdPhysicsController::RelativeRotate(const float rotval[9],bool local) { - if (m_body) + if (m_object) { - m_body->activate(true); - if (m_body->isStaticObject()) + m_object->activate(true); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } btMatrix3x3 drotmat( rotval[0],rotval[4],rotval[8], @@ -374,16 +458,16 @@ void CcdPhysicsController::RelativeRotate(const float rotval[9],bool local) btMatrix3x3 currentOrn; GetWorldOrientation(currentOrn); - btTransform xform = m_body->getCenterOfMassTransform(); - + btTransform xform = m_object->getWorldTransform(); + xform.setBasis(xform.getBasis()*(local ? drotmat : (currentOrn.inverse() * drotmat * currentOrn))); - m_body->setCenterOfMassTransform(xform); + SetCenterOfMassTransform(xform); } - } + void CcdPhysicsController::GetWorldOrientation(btMatrix3x3& mat) { float orn[4]; @@ -394,7 +478,7 @@ void CcdPhysicsController::GetWorldOrientation(btMatrix3x3& mat) void CcdPhysicsController::getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal) { - btQuaternion q = m_body->getCenterOfMassTransform().getRotation(); + btQuaternion q = m_object->getWorldTransform().getRotation(); quatImag0 = q[0]; quatImag1 = q[1]; quatImag2 = q[2]; @@ -402,18 +486,18 @@ void CcdPhysicsController::getOrientation(float &quatImag0,float &quatImag1,flo } void CcdPhysicsController::setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal) { - if (m_body) + if (m_object) { - m_body->activate(true); - if (m_body->isStaticObject()) + m_object->activate(true); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } // not required //m_MotionState->setWorldOrientation(quatImag0,quatImag1,quatImag2,quatReal); - btTransform xform = m_body->getCenterOfMassTransform(); + btTransform xform = m_object->getWorldTransform(); xform.setRotation(btQuaternion(quatImag0,quatImag1,quatImag2,quatReal)); - m_body->setCenterOfMassTransform(xform); + SetCenterOfMassTransform(xform); // not required //m_bulletMotionState->setWorldTransform(xform); } @@ -422,18 +506,18 @@ void CcdPhysicsController::setOrientation(float quatImag0,float quatImag1,float void CcdPhysicsController::setWorldOrientation(const btMatrix3x3& orn) { - if (m_body) + if (m_object) { - m_body->activate(true); - if (m_body->isStaticObject()) + m_object->activate(true); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } // not required //m_MotionState->setWorldOrientation(quatImag0,quatImag1,quatImag2,quatReal); - btTransform xform = m_body->getCenterOfMassTransform(); + btTransform xform = m_object->getWorldTransform(); xform.setBasis(orn); - m_body->setCenterOfMassTransform(xform); + SetCenterOfMassTransform(xform); // not required //m_bulletMotionState->setWorldTransform(xform); } @@ -442,18 +526,18 @@ void CcdPhysicsController::setWorldOrientation(const btMatrix3x3& orn) void CcdPhysicsController::setPosition(float posX,float posY,float posZ) { - if (m_body) + if (m_object) { - m_body->activate(true); - if (m_body->isStaticObject()) + m_object->activate(true); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } // not required, this function is only used to update the physic controller //m_MotionState->setWorldPosition(posX,posY,posZ); - btTransform xform = m_body->getCenterOfMassTransform(); + btTransform xform = m_object->getWorldTransform(); xform.setOrigin(btVector3(posX,posY,posZ)); - m_body->setCenterOfMassTransform(xform); + SetCenterOfMassTransform(xform); // not required //m_bulletMotionState->setWorldTransform(xform); } @@ -466,7 +550,7 @@ void CcdPhysicsController::resolveCombinedVelocities(float linvelX,float linvel void CcdPhysicsController::getPosition(PHY__Vector3& pos) const { - const btTransform& xform = m_body->getCenterOfMassTransform(); + const btTransform& xform = m_object->getWorldTransform(); pos[0] = xform.getOrigin().x(); pos[1] = xform.getOrigin().y(); pos[2] = xform.getOrigin().z(); @@ -480,15 +564,16 @@ void CcdPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ) { m_cci.m_scaling = btVector3(scaleX,scaleY,scaleZ); - if (m_body && m_body->getCollisionShape()) + if (m_object && m_object->getCollisionShape()) { - m_body->getCollisionShape()->setLocalScaling(m_cci.m_scaling); + m_object->getCollisionShape()->setLocalScaling(m_cci.m_scaling); //printf("no inertia recalc for fixed objects with mass=0\n"); - if (m_cci.m_mass) + btRigidBody* body = GetRigidBody(); + if (body && m_cci.m_mass) { - m_body->getCollisionShape()->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor); - m_body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); + body->getCollisionShape()->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor); + body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); } } @@ -499,19 +584,23 @@ void CcdPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ) void CcdPhysicsController::ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local) { btVector3 torque(torqueX,torqueY,torqueZ); - btTransform xform = m_body->getCenterOfMassTransform(); - if (m_body && torque.length2() > (SIMD_EPSILON*SIMD_EPSILON)) + btTransform xform = m_object->getWorldTransform(); + + + if (m_object && torque.length2() > (SIMD_EPSILON*SIMD_EPSILON)) { - m_body->activate(); - if (m_body->isStaticObject()) + btRigidBody* body = GetRigidBody(); + m_object->activate(); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } if (local) { torque = xform.getBasis()*torque; } - m_body->applyTorque(torque); + if (body) + body->applyTorque(torque); } } @@ -519,41 +608,47 @@ void CcdPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bo { btVector3 force(forceX,forceY,forceZ); - if (m_body && force.length2() > (SIMD_EPSILON*SIMD_EPSILON)) + + if (m_object && force.length2() > (SIMD_EPSILON*SIMD_EPSILON)) { - m_body->activate(); - if (m_body->isStaticObject()) + m_object->activate(); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } + + btRigidBody* body = GetRigidBody(); + if (body) { - btTransform xform = m_body->getCenterOfMassTransform(); + btTransform xform = body->getCenterOfMassTransform(); if (local) { force = xform.getBasis()*force; } + body->applyCentralForce(force); } - m_body->applyCentralForce(force); } } void CcdPhysicsController::SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local) { btVector3 angvel(ang_velX,ang_velY,ang_velZ); - if (m_body && angvel.length2() > (SIMD_EPSILON*SIMD_EPSILON)) + if (m_object && angvel.length2() > (SIMD_EPSILON*SIMD_EPSILON)) { - m_body->activate(true); - if (m_body->isStaticObject()) + m_object->activate(true); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } + btRigidBody* body = GetRigidBody(); + if (body) { - btTransform xform = m_body->getCenterOfMassTransform(); + btTransform xform = body->getCenterOfMassTransform(); if (local) { angvel = xform.getBasis()*angvel; } + body->setAngularVelocity(angvel); } - m_body->setAngularVelocity(angvel); } } @@ -561,39 +656,41 @@ void CcdPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,floa { btVector3 linVel(lin_velX,lin_velY,lin_velZ); - if (m_body && linVel.length2() > (SIMD_EPSILON*SIMD_EPSILON)) + if (m_object && linVel.length2() > (SIMD_EPSILON*SIMD_EPSILON)) { - m_body->activate(true); - if (m_body->isStaticObject()) + m_object->activate(true); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } - + btRigidBody* body = GetRigidBody(); + if (body) { - btTransform xform = m_body->getCenterOfMassTransform(); + btTransform xform = m_object->getWorldTransform(); if (local) { linVel = xform.getBasis()*linVel; } + body->setLinearVelocity(linVel); } - m_body->setLinearVelocity(linVel); } } void CcdPhysicsController::applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ) { btVector3 impulse(impulseX,impulseY,impulseZ); - if (m_body && impulse.length2() > (SIMD_EPSILON*SIMD_EPSILON)) + if (m_object && impulse.length2() > (SIMD_EPSILON*SIMD_EPSILON)) { - m_body->activate(); - if (m_body->isStaticObject()) + m_object->activate(); + if (m_object->isStaticObject()) { - m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } btVector3 pos(attachX,attachY,attachZ); - - m_body->applyImpulse(impulse,pos); + btRigidBody* body = GetRigidBody(); + if (body) + body->applyImpulse(impulse,pos); } } @@ -603,29 +700,56 @@ void CcdPhysicsController::SetActive(bool active) // reading out information from physics void CcdPhysicsController::GetLinearVelocity(float& linvX,float& linvY,float& linvZ) { - const btVector3& linvel = this->m_body->getLinearVelocity(); - linvX = linvel.x(); - linvY = linvel.y(); - linvZ = linvel.z(); + btRigidBody* body = GetRigidBody(); + if (body) + { + const btVector3& linvel = body->getLinearVelocity(); + linvX = linvel.x(); + linvY = linvel.y(); + linvZ = linvel.z(); + } else + { + linvX = 0.f; + linvY = 0.f; + linvZ = 0.f; + } } void CcdPhysicsController::GetAngularVelocity(float& angVelX,float& angVelY,float& angVelZ) { - const btVector3& angvel= m_body->getAngularVelocity(); - angVelX = angvel.x(); - angVelY = angvel.y(); - angVelZ = angvel.z(); + btRigidBody* body = GetRigidBody(); + if (body) + { + const btVector3& angvel= body->getAngularVelocity(); + angVelX = angvel.x(); + angVelY = angvel.y(); + angVelZ = angvel.z(); + } else + { + angVelX = 0.f; + angVelY = 0.f; + angVelZ = 0.f; + } } void CcdPhysicsController::GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ) { btVector3 pos(posX,posY,posZ); - btVector3 rel_pos = pos-m_body->getCenterOfMassPosition(); - btVector3 linvel = m_body->getVelocityInLocalPoint(rel_pos); - linvX = linvel.x(); - linvY = linvel.y(); - linvZ = linvel.z(); + btRigidBody* body = GetRigidBody(); + if (body) + { + btVector3 rel_pos = pos-body->getCenterOfMassPosition(); + btVector3 linvel = body->getVelocityInLocalPoint(rel_pos); + linvX = linvel.x(); + linvY = linvel.y(); + linvZ = linvel.z(); + } else + { + linvX = 0.f; + linvY = 0.f; + linvZ = 0.f; + } } void CcdPhysicsController::getReactionForce(float& forceX,float& forceY,float& forceZ) { @@ -636,11 +760,15 @@ void CcdPhysicsController::setRigidBody(bool rigid) { if (!rigid) { - //fake it for now - btVector3 inertia = m_body->getInvInertiaDiagLocal(); - inertia[1] = 0.f; - m_body->setInvInertiaDiagLocal(inertia); - m_body->updateInertiaTensor(); + btRigidBody* body = GetRigidBody(); + if (body) + { + //fake it for now + btVector3 inertia = body->getInvInertiaDiagLocal(); + inertia[1] = 0.f; + body->setInvInertiaDiagLocal(inertia); + body->updateInertiaTensor(); + } } } @@ -657,13 +785,22 @@ void CcdPhysicsController::setNewClientInfo(void* clientinfo) void CcdPhysicsController::UpdateDeactivation(float timeStep) { - m_body->updateDeactivation( timeStep); + btRigidBody* body = GetRigidBody(); + if (body) + { + body->updateDeactivation( timeStep); + } } bool CcdPhysicsController::wantsSleeping() { - - return m_body->wantsSleeping(); + btRigidBody* body = GetRigidBody(); + if (body) + { + return body->wantsSleeping(); + } + //check it out + return true; } PHY_IPhysicsController* CcdPhysicsController::GetReplica() diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 7d55851ebf6..355c1d608b1 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -190,12 +190,15 @@ struct CcdConstructionInfo class btRigidBody; - +class btCollisionObject; +class btSoftBody; ///CcdPhysicsController is a physics object that supports continuous collision detection and time of impact based physics resolution. class CcdPhysicsController : public PHY_IPhysicsController { - btRigidBody* m_body; + + btCollisionObject* m_object; + class PHY_IMotionState* m_MotionState; btMotionState* m_bulletMotionState; class btCollisionShape* m_collisionShape; @@ -231,11 +234,14 @@ class CcdPhysicsController : public PHY_IPhysicsController virtual ~CcdPhysicsController(); - btRigidBody* GetRigidBody() { return m_body;} + btRigidBody* GetRigidBody(); + btCollisionObject* GetCollisionObject(); + btSoftBody* GetSoftBody(); + CcdShapeConstructionInfo* GetShapeInfo() { return m_shapeInfo; } btCollisionShape* GetCollisionShape() { - return m_body->getCollisionShape(); + return m_object->getCollisionShape(); } //////////////////////////////////// // PHY_IPhysicsController interface @@ -310,6 +316,8 @@ class CcdPhysicsController : public PHY_IPhysicsController void UpdateDeactivation(float timeStep); + void SetCenterOfMassTransform(btTransform& xform); + static btTransform GetTransformFromMotionState(PHY_IMotionState* motionState); void setAabb(const btVector3& aabbMin,const btVector3& aabbMax); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 5042df2162a..96caf885e7c 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -23,6 +23,7 @@ subject to the following restrictions: #include "btBulletDynamicsCommon.h" #include "LinearMath/btIDebugDraw.h" #include "BulletCollision/CollisionDispatch/btSimulationIslandManager.h" +#include "BulletSoftBody/btSoftRigidDynamicsWorld.h" //profiling/timings #include "LinearMath/btQuickprof.h" @@ -344,7 +345,9 @@ m_filterCallback(NULL) m_broadphase->getOverlappingPairCache()->setOverlapFilterCallback(m_filterCallback); setSolverType(1);//issues with quickstep and memory allocations - m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration); +// m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + m_dynamicsWorld = new btSoftRigidDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + m_debugDrawer = 0; m_gravity = btVector3(0.f,-10.f,0.f); m_dynamicsWorld->setGravity(m_gravity); @@ -355,24 +358,43 @@ m_filterCallback(NULL) void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl) { btRigidBody* body = ctrl->GetRigidBody(); + btCollisionObject* obj = ctrl->GetCollisionObject(); //this m_userPointer is just used for triggers, see CallbackTriggers - body->setUserPointer(ctrl); + obj->setUserPointer(ctrl); + if (body) + body->setGravity( m_gravity ); - body->setGravity( m_gravity ); m_controllers.insert(ctrl); - //use explicit group/filter for finer control over collision in bullet => near/radar sensor - m_dynamicsWorld->addRigidBody(body, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); - if (body->isStaticOrKinematicObject()) + if (body) { - body->setActivationState(ISLAND_SLEEPING); + //use explicit group/filter for finer control over collision in bullet => near/radar sensor + m_dynamicsWorld->addRigidBody(body, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); + } else + { + if (ctrl->GetSoftBody()) + { + //not yet + btAssert(0); + //m_dynamicsWorld->addSo + } else + { + if (obj->getCollisionShape()) + { + m_dynamicsWorld->addCollisionObject(obj,ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); + } + } + } + if (obj->isStaticOrKinematicObject()) + { + obj->setActivationState(ISLAND_SLEEPING); } //CollisionObject(body,ctrl->GetCollisionFilterGroup(),ctrl->GetCollisionFilterMask()); - assert(body->getBroadphaseHandle()); + assert(obj->getBroadphaseHandle()); btBroadphaseInterface* scene = getBroadphase(); @@ -381,7 +403,7 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl) assert(shapeinterface); - const btTransform& t = ctrl->GetRigidBody()->getCenterOfMassTransform(); + const btTransform& t = ctrl->GetCollisionObject()->getWorldTransform(); btPoint3 minAabb,maxAabb; @@ -393,32 +415,34 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl) //extent it with the motion - btVector3 linMotion = body->getLinearVelocity()*timeStep; + if (body) + { + btVector3 linMotion = body->getLinearVelocity()*timeStep; - float maxAabbx = maxAabb.getX(); - float maxAabby = maxAabb.getY(); - float maxAabbz = maxAabb.getZ(); - float minAabbx = minAabb.getX(); - float minAabby = minAabb.getY(); - float minAabbz = minAabb.getZ(); + float maxAabbx = maxAabb.getX(); + float maxAabby = maxAabb.getY(); + float maxAabbz = maxAabb.getZ(); + float minAabbx = minAabb.getX(); + float minAabby = minAabb.getY(); + float minAabbz = minAabb.getZ(); - if (linMotion.x() > 0.f) - maxAabbx += linMotion.x(); - else - minAabbx += linMotion.x(); - if (linMotion.y() > 0.f) - maxAabby += linMotion.y(); - else - minAabby += linMotion.y(); - if (linMotion.z() > 0.f) - maxAabbz += linMotion.z(); - else - minAabbz += linMotion.z(); + if (linMotion.x() > 0.f) + maxAabbx += linMotion.x(); + else + minAabbx += linMotion.x(); + if (linMotion.y() > 0.f) + maxAabby += linMotion.y(); + else + minAabby += linMotion.y(); + if (linMotion.z() > 0.f) + maxAabbz += linMotion.z(); + else + minAabbz += linMotion.z(); - minAabb = btVector3(minAabbx,minAabby,minAabbz); - maxAabb = btVector3(maxAabbx,maxAabby,maxAabbz); - + minAabb = btVector3(minAabbx,minAabby,minAabbz); + maxAabb = btVector3(maxAabbx,maxAabby,maxAabbz); + } @@ -427,8 +451,22 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl) void CcdPhysicsEnvironment::removeCcdPhysicsController(CcdPhysicsController* ctrl) { //also remove constraint - - m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody()); + btRigidBody* body = ctrl->GetRigidBody(); + if (body) + { + m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody()); + } else + { + //if a softbody + if (ctrl->GetSoftBody()) + { + //not yet + btAssert(0); + } else + { + m_dynamicsWorld->removeCollisionObject(ctrl->GetCollisionObject()); + } + } m_controllers.erase(ctrl); if (ctrl->m_registerCount != 0) @@ -443,14 +481,20 @@ void CcdPhysicsEnvironment::updateCcdPhysicsController(CcdPhysicsController* ctr // this function is used when the collisionning group of a controller is changed // remove and add the collistioning object btRigidBody* body = ctrl->GetRigidBody(); - btVector3 inertia(0.0,0.0,0.0); - - m_dynamicsWorld->removeCollisionObject(body); - body->setCollisionFlags(newCollisionFlags); - if (newMass) - body->getCollisionShape()->calculateLocalInertia(newMass, inertia); - body->setMassProps(newMass, inertia); - m_dynamicsWorld->addCollisionObject(body, newCollisionGroup, newCollisionMask); + btCollisionObject* obj = ctrl->GetCollisionObject(); + if (obj) + { + btVector3 inertia(0.0,0.0,0.0); + m_dynamicsWorld->removeCollisionObject(obj); + obj->setCollisionFlags(newCollisionFlags); + if (body) + { + if (newMass) + body->getCollisionShape()->calculateLocalInertia(newMass, inertia); + body->setMassProps(newMass, inertia); + } + m_dynamicsWorld->addCollisionObject(obj, newCollisionGroup, newCollisionMask); + } // to avoid nasty interaction, we must update the property of the controller as well ctrl->m_cci.m_mass = newMass; ctrl->m_cci.m_collisionFilterGroup = newCollisionGroup; @@ -462,9 +506,9 @@ void CcdPhysicsEnvironment::enableCcdPhysicsController(CcdPhysicsController* ctr { if (m_controllers.insert(ctrl).second) { - btRigidBody* body = ctrl->GetRigidBody(); - body->setUserPointer(ctrl); - m_dynamicsWorld->addCollisionObject(body, + btCollisionObject* obj = ctrl->GetCollisionObject(); + obj->setUserPointer(ctrl); + m_dynamicsWorld->addCollisionObject(obj, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); } } @@ -473,7 +517,19 @@ void CcdPhysicsEnvironment::disableCcdPhysicsController(CcdPhysicsController* ct { if (m_controllers.erase(ctrl)) { - m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody()); + btRigidBody* body = ctrl->GetRigidBody(); + if (body) + { + m_dynamicsWorld->removeRigidBody(body); + } else + { + if (ctrl->GetSoftBody()) + { + } else + { + m_dynamicsWorld->removeCollisionObject(body); + } + } } } @@ -792,7 +848,7 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac CcdShapeConstructionInfo* shapeInfo = controller->m_shapeInfo; if (shapeInfo) { - btCollisionShape* shape = controller->GetRigidBody()->getCollisionShape(); + btCollisionShape* shape = controller->GetCollisionObject()->getCollisionShape(); if (shape->isCompound()) { btCompoundShape* compoundShape = (btCompoundShape*)shape; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 3cf5a943e3f..3569cf25b68 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -233,13 +233,13 @@ protected: std::vector m_wrapperVehicles; - //use explicit btDiscreteDynamicsWorld* so that we have access to + //use explicit btSoftRigidDynamicsWorld/btDiscreteDynamicsWorld* so that we have access to //btDiscreteDynamicsWorld::addRigidBody(body,filter,group) //so that we can set the body collision filter/group at the time of creation //and not afterwards (breaks the collision system for radar/near sensor) //Ideally we would like to have access to this function from the btDynamicsWorld interface //class btDynamicsWorld* m_dynamicsWorld; - class btDiscreteDynamicsWorld* m_dynamicsWorld; + class btSoftRigidDynamicsWorld* m_dynamicsWorld; class btConstraintSolver* m_solver; From 651c0e48610433fa0823a3d94d30ee608860eb49 Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Wed, 17 Sep 2008 02:30:19 +0000 Subject: [PATCH 105/125] Applied some fixes from Bullet: issues with btDbvtBroadphase, and btSoftBody, and better fix for 64-bit issue in btCompoundCollisionAlgorithm. --- .../BroadphaseCollision/btDbvt.h | 1 + .../BroadphaseCollision/btDbvtBroadphase.cpp | 275 +++++++++++++++--- .../BroadphaseCollision/btDbvtBroadphase.h | 28 +- .../btCompoundCollisionAlgorithm.cpp | 2 +- .../bullet2/src/BulletSoftBody/btSoftBody.cpp | 36 ++- .../bullet2/src/BulletSoftBody/btSoftBody.h | 3 + 6 files changed, 285 insertions(+), 60 deletions(-) diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h index da296445e81..21d69acf151 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvt.h @@ -188,6 +188,7 @@ struct btDbvtNode union { btDbvtNode* childs[2]; void* data; + int dataAsInt; }; }; diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp index c6086f28f19..fd82fd7cae3 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.cpp @@ -20,17 +20,18 @@ subject to the following restrictions: // Profiling // -#if DBVT_BP_PROFILE +#if DBVT_BP_PROFILE||DBVT_BP_ENABLE_BENCHMARK #include +#endif + +#if DBVT_BP_PROFILE struct ProfileScope { - ProfileScope(btClock& clock,unsigned long& value) + __forceinline ProfileScope(btClock& clock,unsigned long& value) : + m_clock(&clock),m_value(&value),m_base(clock.getTimeMicroseconds()) { - m_clock=&clock; - m_value=&value; - m_base=clock.getTimeMicroseconds(); } - ~ProfileScope() + __forceinline ~ProfileScope() { (*m_value)+=m_clock->getTimeMicroseconds()-m_base; } @@ -90,19 +91,25 @@ value=zerodummy; struct btDbvtTreeCollider : btDbvt::ICollide { btDbvtBroadphase* pbp; +btDbvtProxy* proxy; btDbvtTreeCollider(btDbvtBroadphase* p) : pbp(p) {} void Process(const btDbvtNode* na,const btDbvtNode* nb) { - btDbvtProxy* pa=(btDbvtProxy*)na->data; - btDbvtProxy* pb=(btDbvtProxy*)nb->data; - #if DBVT_BP_DISCRETPAIRS - if(Intersect(pa->aabb,pb->aabb)) - #endif + if(na!=nb) { + btDbvtProxy* pa=(btDbvtProxy*)na->data; + btDbvtProxy* pb=(btDbvtProxy*)nb->data; + #if DBVT_BP_SORTPAIRS if(pa>pb) btSwap(pa,pb); + #endif pbp->m_paircache->addOverlappingPair(pa,pb); + ++pbp->m_newpairs; } } +void Process(const btDbvtNode* n) + { + Process(n,proxy->leaf); + } }; // @@ -112,16 +119,25 @@ void Process(const btDbvtNode* na,const btDbvtNode* nb) // btDbvtBroadphase::btDbvtBroadphase(btOverlappingPairCache* paircache) { +m_deferedcollide = false; +m_needcleanup = true; m_releasepaircache = (paircache!=0)?false:true; -m_predictedframes = 2; +m_prediction = 1/(btScalar)2; m_stageCurrent = 0; +m_fixedleft = 0; m_fupdates = 1; -m_dupdates = 1; +m_dupdates = 0; +m_cupdates = 10; +m_newpairs = 1; +m_updates_call = 0; +m_updates_done = 0; +m_updates_ratio = 0; m_paircache = paircache? - paircache : - new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); + paircache : + new(btAlignedAlloc(sizeof(btHashedOverlappingPairCache),16)) btHashedOverlappingPairCache(); m_gid = 0; m_pid = 0; +m_cid = 0; for(int i=0;i<=STAGECOUNT;++i) { m_stageRoots[i]=0; @@ -148,17 +164,23 @@ btBroadphaseProxy* btDbvtBroadphase::createProxy( const btVector3& aabbMin, void* userPtr, short int collisionFilterGroup, short int collisionFilterMask, - btDispatcher* /*dispatcher*/, + btDispatcher* dispatcher, void* /*multiSapProxy*/) { -btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( userPtr, - collisionFilterGroup, - collisionFilterMask); +btDbvtProxy* proxy=new(btAlignedAlloc(sizeof(btDbvtProxy),16)) btDbvtProxy( userPtr, + collisionFilterGroup, + collisionFilterMask); proxy->aabb = btDbvtVolume::FromMM(aabbMin,aabbMax); -proxy->leaf = m_sets[0].insert(proxy->aabb,proxy); proxy->stage = m_stageCurrent; proxy->m_uniqueId = ++m_gid; +proxy->leaf = m_sets[0].insert(proxy->aabb,proxy); listappend(proxy,m_stageRoots[m_stageCurrent]); +if(!m_deferedcollide) + { + btDbvtTreeCollider collider(this); + collider.proxy=proxy; + btDbvt::collideTV(m_sets[0].m_root,proxy->aabb,collider); + } return(proxy); } @@ -174,6 +196,7 @@ if(proxy->stage==STAGECOUNT) listremove(proxy,m_stageRoots[proxy->stage]); m_paircache->removeOverlappingPairsContainingProxy(proxy,dispatcher); btAlignedFree(proxy); +m_needcleanup=true; } // @@ -182,35 +205,62 @@ void btDbvtBroadphase::setAabb( btBroadphaseProxy* absproxy, const btVector3& aabbMax, btDispatcher* /*dispatcher*/) { -btDbvtProxy* proxy=(btDbvtProxy*)absproxy; -btDbvtVolume aabb=btDbvtVolume::FromMM(aabbMin,aabbMax); +btDbvtProxy* proxy=(btDbvtProxy*)absproxy; +ATTRIBUTE_ALIGNED16(btDbvtVolume) aabb=btDbvtVolume::FromMM(aabbMin,aabbMax); +#if DBVT_BP_PREVENTFALSEUPDATE if(NotEqual(aabb,proxy->leaf->volume)) +#endif { + bool docollide=false; if(proxy->stage==STAGECOUNT) {/* fixed -> dynamic set */ m_sets[1].remove(proxy->leaf); proxy->leaf=m_sets[0].insert(aabb,proxy); + docollide=true; } else {/* dynamic set */ + ++m_updates_call; if(Intersect(proxy->leaf->volume,aabb)) {/* Moving */ - const btVector3 delta=(aabbMin+aabbMax)/2-proxy->aabb.Center(); - #ifdef DBVT_BP_MARGIN - m_sets[0].update(proxy->leaf,aabb,delta*m_predictedframes,DBVT_BP_MARGIN); - #else - m_sets[0].update(proxy->leaf,aabb,delta*m_predictedframes); - #endif + const btVector3 delta=aabbMin-proxy->aabb.Mins(); + btVector3 velocity(aabb.Extents()*m_prediction); + if(delta[0]<0) velocity[0]=-velocity[0]; + if(delta[1]<0) velocity[1]=-velocity[1]; + if(delta[2]<0) velocity[2]=-velocity[2]; + if ( + #ifdef DBVT_BP_MARGIN + m_sets[0].update(proxy->leaf,aabb,velocity,DBVT_BP_MARGIN) + #else + m_sets[0].update(proxy->leaf,aabb,velocity) + #endif + ) + { + ++m_updates_done; + docollide=true; + } } else {/* Teleporting */ - m_sets[0].update(proxy->leaf,aabb); + m_sets[0].update(proxy->leaf,aabb); + ++m_updates_done; + docollide=true; } } listremove(proxy,m_stageRoots[proxy->stage]); proxy->aabb = aabb; proxy->stage = m_stageCurrent; listappend(proxy,m_stageRoots[m_stageCurrent]); + if(docollide) + { + m_needcleanup=true; + if(!m_deferedcollide) + { + btDbvtTreeCollider collider(this); + btDbvt::collideTT(m_sets[1].m_root,proxy->leaf,collider); + btDbvt::collideTT(m_sets[0].m_root,proxy->leaf,collider); + } + } } } @@ -245,7 +295,12 @@ void btDbvtBroadphase::collide(btDispatcher* dispatcher) SPC(m_profiling.m_total); /* optimize */ m_sets[0].optimizeIncremental(1+(m_sets[0].m_leaves*m_dupdates)/100); -m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100); +if(m_fixedleft) + { + const int count=1+(m_sets[1].m_leaves*m_fupdates)/100; + m_sets[1].optimizeIncremental(1+(m_sets[1].m_leaves*m_fupdates)/100); + m_fixedleft=btMax(0,m_fixedleft-count); + } /* dynamic -> fixed set */ m_stageCurrent=(m_stageCurrent+1)%STAGECOUNT; btDbvtProxy* current=m_stageRoots[m_stageCurrent]; @@ -256,46 +311,69 @@ if(current) btDbvtProxy* next=current->links[1]; listremove(current,m_stageRoots[current->stage]); listappend(current,m_stageRoots[STAGECOUNT]); - btDbvt::collideTT(m_sets[1].m_root,current->leaf,collider); + #if DBVT_BP_ACCURATESLEEPING + m_paircache->removeOverlappingPairsContainingProxy(current,dispatcher); + collider.proxy=current; + btDbvt::collideTV(m_sets[0].m_root,current->aabb,collider); + btDbvt::collideTV(m_sets[1].m_root,current->aabb,collider); + #endif m_sets[0].remove(current->leaf); current->leaf = m_sets[1].insert(current->aabb,current); current->stage = STAGECOUNT; current = next; } while(current); + m_fixedleft=m_sets[1].m_leaves; + m_needcleanup=true; } /* collide dynamics */ { btDbvtTreeCollider collider(this); + if(m_deferedcollide) { SPC(m_profiling.m_fdcollide); btDbvt::collideTT(m_sets[0].m_root,m_sets[1].m_root,collider); } + if(m_deferedcollide) { SPC(m_profiling.m_ddcollide); btDbvt::collideTT(m_sets[0].m_root,m_sets[0].m_root,collider); } } /* clean up */ +if(m_needcleanup) { SPC(m_profiling.m_cleanup); btBroadphasePairArray& pairs=m_paircache->getOverlappingPairArray(); if(pairs.size()>0) { - for(int i=0,ni=pairs.size();i(m_newpairs,(ci*m_cupdates)/100)); + for(int i=0;iaabb,pb->aabb)) + btBroadphasePair& p=pairs[(m_cid+i)%ci]; + btDbvtProxy* pa=(btDbvtProxy*)p.m_pProxy0; + btDbvtProxy* pb=(btDbvtProxy*)p.m_pProxy1; + if(!Intersect(pa->leaf->volume,pb->leaf->volume)) { + #if DBVT_BP_SORTPAIRS if(pa>pb) btSwap(pa,pb); + #endif m_paircache->removeOverlappingPair(pa,pb,dispatcher); --ni;--i; } } + if(pairs.size()>0) m_cid=(m_cid+ni)%pairs.size(); else m_cid=0; } } ++m_pid; +m_newpairs=1; +m_needcleanup=false; +if(m_updates_call>0) + { m_updates_ratio=m_updates_done/(btScalar)m_updates_call; } + else + { m_updates_ratio=0; } +m_updates_done/=2; +m_updates_call/=2; } // @@ -339,6 +417,131 @@ aabbMax=bounds.Maxs(); void btDbvtBroadphase::printStats() {} +// +#if DBVT_BP_ENABLE_BENCHMARK + +struct btBroadphaseBenchmark + { + struct Experiment + { + const char* name; + int object_count; + int update_count; + int spawn_count; + int iterations; + btScalar speed; + btScalar amplitude; + }; + struct Object + { + btVector3 center; + btVector3 extents; + btBroadphaseProxy* proxy; + btScalar time; + void update(btScalar speed,btScalar amplitude,btBroadphaseInterface* pbi) + { + time += speed; + center[0] = btCos(time*(btScalar)2.17)*amplitude+ + btSin(time)*amplitude/2; + center[1] = btCos(time*(btScalar)1.38)*amplitude+ + btSin(time)*amplitude; + center[2] = btSin(time*(btScalar)0.777)*amplitude; + pbi->setAabb(proxy,center-extents,center+extents,0); + } + }; + static int UnsignedRand(int range=RAND_MAX-1) { return(rand()%(range+1)); } + static btScalar UnitRand() { return(UnsignedRand(16384)/(btScalar)16384); } + static void OutputTime(const char* name,btClock& c,unsigned count=0) + { + const unsigned long us=c.getTimeMicroseconds(); + const unsigned long ms=(us+500)/1000; + const btScalar sec=us/(btScalar)(1000*1000); + if(count>0) + printf("%s : %u us (%u ms), %.2f/s\r\n",name,us,ms,count/sec); + else + printf("%s : %u us (%u ms)\r\n",name,us,ms); + } + }; + +void btDbvtBroadphase::benchmark(btBroadphaseInterface* pbi) +{ +static const btBroadphaseBenchmark::Experiment experiments[]= + { + {"1024o.10%",1024,10,0,8192,(btScalar)0.005,(btScalar)100}, + /*{"4096o.10%",4096,10,0,8192,(btScalar)0.005,(btScalar)100}, + {"8192o.10%",8192,10,0,8192,(btScalar)0.005,(btScalar)100},*/ + }; +static const int nexperiments=sizeof(experiments)/sizeof(experiments[0]); +btAlignedObjectArray objects; +btClock wallclock; +/* Begin */ +for(int iexp=0;iexpcenter[0]=btBroadphaseBenchmark::UnitRand()*50; + po->center[1]=btBroadphaseBenchmark::UnitRand()*50; + po->center[2]=btBroadphaseBenchmark::UnitRand()*50; + po->extents[0]=btBroadphaseBenchmark::UnitRand()*2+2; + po->extents[1]=btBroadphaseBenchmark::UnitRand()*2+2; + po->extents[2]=btBroadphaseBenchmark::UnitRand()*2+2; + po->time=btBroadphaseBenchmark::UnitRand()*2000; + po->proxy=pbi->createProxy(po->center-po->extents,po->center+po->extents,0,po,1,1,0,0); + objects.push_back(po); + } + btBroadphaseBenchmark::OutputTime("\tInitialization",wallclock); + /* First update */ + wallclock.reset(); + for(int i=0;iupdate(speed,amplitude,pbi); + } + btBroadphaseBenchmark::OutputTime("\tFirst update",wallclock); + /* Updates */ + wallclock.reset(); + for(int i=0;iupdate(speed,amplitude,pbi); + } + pbi->calculateOverlappingPairs(0); + } + btBroadphaseBenchmark::OutputTime("\tUpdate",wallclock,experiment.iterations); + /* Clean up */ + wallclock.reset(); + for(int i=0;idestroyProxy(objects[i]->proxy,0); + delete objects[i]; + } + objects.resize(0); + btBroadphaseBenchmark::OutputTime("\tRelease",wallclock); + } + +} +#else +void btDbvtBroadphase::benchmark(btBroadphaseInterface*) +{} +#endif + #if DBVT_BP_PROFILE #undef SPC #endif diff --git a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h index 3f19075552b..4576e48f3f4 100644 --- a/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h +++ b/extern/bullet2/src/BulletCollision/BroadphaseCollision/btDbvtBroadphase.h @@ -23,9 +23,12 @@ subject to the following restrictions: // Compile time config // -#define DBVT_BP_PROFILE 0 -#define DBVT_BP_DISCRETPAIRS 1 -#define DBVT_BP_MARGIN (btScalar)0.05 +#define DBVT_BP_PROFILE 0 +#define DBVT_BP_SORTPAIRS 1 +#define DBVT_BP_PREVENTFALSEUPDATE 0 +#define DBVT_BP_ACCURATESLEEPING 0 +#define DBVT_BP_ENABLE_BENCHMARK 0 +#define DBVT_BP_MARGIN (btScalar)0.05 #if DBVT_BP_PROFILE #define DBVT_BP_PROFILING_RATE 256 @@ -38,10 +41,10 @@ subject to the following restrictions: struct btDbvtProxy : btBroadphaseProxy { /* Fields */ -btDbvtAabbMm aabb; +btDbvtAabbMm aabb; btDbvtNode* leaf; -btDbvtProxy* links[2]; -int stage; +btDbvtProxy* links[2]; +int stage; /* ctor */ btDbvtProxy(void* userPtr,short int collisionFilterGroup, short int collisionFilterMask) : btBroadphaseProxy(userPtr,collisionFilterGroup,collisionFilterMask) @@ -67,13 +70,23 @@ enum { btDbvt m_sets[2]; // Dbvt sets btDbvtProxy* m_stageRoots[STAGECOUNT+1]; // Stages list btOverlappingPairCache* m_paircache; // Pair cache -btScalar m_predictedframes; // Frames predicted +btScalar m_prediction; // Velocity prediction int m_stageCurrent; // Current stage int m_fupdates; // % of fixed updates per frame int m_dupdates; // % of dynamic updates per frame +int m_cupdates; // % of cleanup updates per frame +int m_newpairs; // Number of pairs created +int m_fixedleft; // Fixed optimization left +unsigned m_updates_call; // Number of updates call +unsigned m_updates_done; // Number of updates done +btScalar m_updates_ratio; // m_updates_done/m_updates_call int m_pid; // Parse id +int m_cid; // Cleanup index int m_gid; // Gen id bool m_releasepaircache; // Release pair cache on delete +bool m_deferedcollide; // Defere dynamic/static collision to collide call +bool m_needcleanup; // Need to run cleanup? +bool m_initialize; // Initialization #if DBVT_BP_PROFILE btClock m_clock; struct { @@ -98,6 +111,7 @@ btOverlappingPairCache* getOverlappingPairCache(); const btOverlappingPairCache* getOverlappingPairCache() const; void getBroadphaseAabb(btVector3& aabbMin,btVector3& aabbMax) const; void printStats(); +static void benchmark(btBroadphaseInterface*); }; #endif diff --git a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp index 57812818007..535b61992b0 100644 --- a/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp +++ b/extern/bullet2/src/BulletCollision/CollisionDispatch/btCompoundCollisionAlgorithm.cpp @@ -141,7 +141,7 @@ public: } void Process(const btDbvtNode* leaf) { - int index = int(long(leaf->data)); + int index = leaf->dataAsInt; btCompoundShape* compoundShape = static_cast(m_compoundColObj->getCollisionShape()); btCollisionShape* childShape = compoundShape->getChildShape(index); diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp index 2553009fec2..91b9d6f1bbd 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.cpp @@ -97,8 +97,7 @@ btSoftBody::~btSoftBody() delete m_collisionShape; int i; - for(i=0;im_leaf) m_cdbvt.remove(c->m_leaf); +c->~Cluster(); +btAlignedFree(c); +m_clusters.remove(c); +} + +// +void btSoftBody::releaseClusters() +{ +while(m_clusters.size()>0) releaseCluster(0); +} + // int btSoftBody::generateClusters(int k,int maxiterations) { - int i; - -for(i=0;im_leaf) m_cdbvt.remove(m_clusters[i]->m_leaf); - btAlignedFree(m_clusters[i]); - } +int i; +releaseClusters(); m_clusters.resize(btMin(k,m_nodes.size())); - - - for(i=0;i0) { if(m_clusters[i]->m_nodes.size()==0) { - btAlignedFree(m_clusters[i]); - btSwap(m_clusters[i],m_clusters[m_clusters.size()-1]); - m_clusters.pop_back(); - --i; + releaseCluster(i--); } } diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBody.h b/extern/bullet2/src/BulletSoftBody/btSoftBody.h index 834199c668a..91d732b4e9a 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBody.h +++ b/extern/bullet2/src/BulletSoftBody/btSoftBody.h @@ -717,6 +717,9 @@ public: Material* mat=0); /* Randomize constraints to reduce solver bias */ void randomizeConstraints(); + /* Release clusters */ + void releaseCluster(int index); + void releaseClusters(); /* Generate clusters (K-mean) */ int generateClusters(int k,int maxiterations=8192); /* Refine */ From 4cd85aa61c3fe104e95b2b88669e6e8f1b796458 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 17 Sep 2008 03:13:15 +0000 Subject: [PATCH 106/125] Texture_getHFracDim was returning an int rather then a float (thanks zuegs for spotting) removed unused var --- source/blender/python/api2_2x/Texture.c | 2 +- source/blender/src/editmesh_lib.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/source/blender/python/api2_2x/Texture.c b/source/blender/python/api2_2x/Texture.c index 141b36a05d6..51e1c389528 100644 --- a/source/blender/python/api2_2x/Texture.c +++ b/source/blender/python/api2_2x/Texture.c @@ -2132,7 +2132,7 @@ static PyObject *Texture_getFlags( BPy_Texture *self ) static PyObject *Texture_getHFracDim( BPy_Texture *self ) { - return PyInt_FromLong( (long)self->texture->mg_H ); + return PyFloat_FromDouble( self->texture->mg_H ); } static PyObject *Texture_getImageFlags( BPy_Texture *self, void *type ) diff --git a/source/blender/src/editmesh_lib.c b/source/blender/src/editmesh_lib.c index 1aa1642d597..bafc9dda7d6 100644 --- a/source/blender/src/editmesh_lib.c +++ b/source/blender/src/editmesh_lib.c @@ -1906,7 +1906,6 @@ void flip_editnormals(void) { EditMesh *em = G.editMesh; EditFace *efa; - EditVert *eve; efa= em->faces.first; while(efa) { From 36e2004fcae3b5cd65bcceebed46326ff5debe69 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Wed, 17 Sep 2008 04:06:59 +0000 Subject: [PATCH 107/125] Delete Keyframe Tool: * Changed hotkey to Alt-I. As a result, Remove IK is now Ctrl-Alt-I, though that shouldn't affect many people at all as it appears that hardly anyone uses it. * Added menu entries for Delete Keyframe --- source/blender/src/header_view3d.c | 22 +++++++++++++++++++++- source/blender/src/space.c | 2 +- source/blender/src/toets.c | 2 +- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/source/blender/src/header_view3d.c b/source/blender/src/header_view3d.c index acd80f5efdd..36ba819b3f1 100644 --- a/source/blender/src/header_view3d.c +++ b/source/blender/src/header_view3d.c @@ -2523,6 +2523,9 @@ static void do_view3d_edit_objectmenu(void *arg, int event) if(session) b_verse_push_object(session, ob); break; #endif + case 18: /* delete keyframe */ + common_deletekey(); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -2559,6 +2562,7 @@ static uiBlock *view3d_edit_objectmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 11, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Keyframe|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 18, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -3151,6 +3155,9 @@ static void do_view3d_edit_meshmenu(void *arg, int event) case 15: uv_autocalc_tface(); break; + case 16: /* delete keyframe */ + common_deletekey(); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -3186,6 +3193,7 @@ static uiBlock *view3d_edit_meshmenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Keyframe|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -3417,6 +3425,9 @@ static void do_view3d_edit_curvemenu(void *arg, int event) case 15: uv_autocalc_tface(); break; + case 16: /* delete keyframe */ + common_deletekey(); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -3441,6 +3452,7 @@ static uiBlock *view3d_edit_curvemenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Keyframe|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 16, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -3761,6 +3773,9 @@ static void do_view3d_edit_latticemenu(void *arg, int event) case 6: uv_autocalc_tface(); break; + case 7: /* delete keyframe */ + common_deletekey(); + break; } allqueue(REDRAWVIEW3D, 0); } @@ -3784,6 +3799,7 @@ static uiBlock *view3d_edit_latticemenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Keyframe|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 7, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); @@ -4171,7 +4187,7 @@ static uiBlock *view3d_pose_armature_ikmenu(void *arg_unused) uiBlockSetButmFunc(block, do_view3d_pose_armature_ikmenu, NULL); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Add IK to Bone...|Shift I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 1, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear IK...|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Clear IK...|Ctrl Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 2, ""); uiBlockSetDirection(block, UI_RIGHT); uiTextBoundsBlock(block, 60); @@ -4374,6 +4390,9 @@ static void do_view3d_pose_armaturemenu(void *arg, int event) case 19: /* assign pose as restpose */ apply_armature_pose2bones(); break; + case 20: /* delete keyframe */ + common_deletekey(); + break; } allqueue(REDRAWVIEW3D, 0); @@ -4395,6 +4414,7 @@ static uiBlock *view3d_pose_armaturemenu(void *arg_unused) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Insert Keyframe|I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 4, ""); + uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Delete Keyframe|Alt I", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, 20, ""); uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 9120fc3de76..140ec59e360 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -2218,7 +2218,7 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt) else selectswap(); } - else if(G.qual==LR_ALTKEY) { + else if(G.qual==(LR_CTRLKEY|LR_ALTKEY)) { if(ob && (ob->flag & OB_POSEMODE) && ob->type==OB_ARMATURE) pose_clear_IK(); } diff --git a/source/blender/src/toets.c b/source/blender/src/toets.c index 41ee557c9c2..df0a2921578 100644 --- a/source/blender/src/toets.c +++ b/source/blender/src/toets.c @@ -793,7 +793,7 @@ int blenderqread(unsigned short event, short val) ob= OBACT; if(G.f & G_SCULPTMODE) return 1; - else if(G.qual==(LR_CTRLKEY|LR_ALTKEY)) { + else if(G.qual==LR_ALTKEY) { common_deletekey(); return 0; } From f0e0e6b1c92b8fdcb1fd2828ee9f9da0048f8ff0 Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Wed, 17 Sep 2008 04:07:58 +0000 Subject: [PATCH 108/125] * Some tweaks to the OBJ importer/exporter after chatting with Campbell - renamed the 'morph target' option to 'keep vertex order' - enabled 'keep vertex order' by default This should improve usability for importing and exporting shape keys, point caches, mdds ,etc. --- release/scripts/export_obj.py | 14 +++++++------- release/scripts/import_obj.py | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/release/scripts/export_obj.py b/release/scripts/export_obj.py index 8e7374f02b5..6ea890879dd 100644 --- a/release/scripts/export_obj.py +++ b/release/scripts/export_obj.py @@ -185,7 +185,7 @@ def write(filename, objects,\ EXPORT_TRI=False, EXPORT_EDGES=False, EXPORT_NORMALS=False, EXPORT_NORMALS_HQ=False,\ EXPORT_UV=True, EXPORT_MTL=True, EXPORT_COPY_IMAGES=False,\ EXPORT_APPLY_MODIFIERS=True, EXPORT_ROTX90=True, EXPORT_BLEN_OBS=True,\ -EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_MORPH_TARGET=False): +EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_KEEP_VERT_ORDER=False): ''' Basic write function. The context and options must be alredy set This can be accessed externaly @@ -322,7 +322,7 @@ EXPORT_GROUP_BY_OB=False, EXPORT_GROUP_BY_MAT=False, EXPORT_MORPH_TARGET=False) # Sort by Material, then images # so we dont over context switch in the obj file. - if EXPORT_MORPH_TARGET: + if EXPORT_KEEP_VERT_ORDER: pass elif faceuv: try: faces.sort(key = lambda a: (a.mat, a.image, a.smooth)) @@ -550,7 +550,7 @@ def write_ui(filename): EXPORT_BLEN_OBS = Draw.Create(1) EXPORT_GROUP_BY_OB = Draw.Create(0) EXPORT_GROUP_BY_MAT = Draw.Create(0) - EXPORT_MORPH_TARGET = Draw.Create(0) + EXPORT_KEEP_VERT_ORDER = Draw.Create(1) # removed too many options are bad! @@ -563,7 +563,7 @@ def write_ui(filename): ('Object Prefs...'),\ ('Apply Modifiers', EXPORT_APPLY_MODIFIERS, 'Use transformed mesh data from each object. May break vert order for morph targets.'),\ ('Rotate X90', EXPORT_ROTX90 , 'Rotate on export so Blenders UP is translated into OBJs UP'),\ - ('Morph Target', EXPORT_MORPH_TARGET, 'Keep vert and face order, disables some other options.'),\ + ('Keep Vert Order', EXPORT_KEEP_VERT_ORDER, 'Keep vert and face order, disables some other options.'),\ ('Extra Data...'),\ ('Edges', EXPORT_EDGES, 'Edges not connected to faces.'),\ ('Normals', EXPORT_NORMALS, 'Export vertex normal data (Ignored on import).'),\ @@ -581,7 +581,7 @@ def write_ui(filename): if not Draw.PupBlock('Export...', pup_block): return - if EXPORT_MORPH_TARGET.val: + if EXPORT_KEEP_VERT_ORDER.val: EXPORT_BLEN_OBS.val = False EXPORT_GROUP_BY_OB.val = False EXPORT_GROUP_BY_MAT.val = False @@ -606,7 +606,7 @@ def write_ui(filename): EXPORT_BLEN_OBS = EXPORT_BLEN_OBS.val EXPORT_GROUP_BY_OB = EXPORT_GROUP_BY_OB.val EXPORT_GROUP_BY_MAT = EXPORT_GROUP_BY_MAT.val - EXPORT_MORPH_TARGET = EXPORT_MORPH_TARGET.val + EXPORT_KEEP_VERT_ORDER = EXPORT_KEEP_VERT_ORDER.val @@ -656,7 +656,7 @@ def write_ui(filename): EXPORT_NORMALS_HQ, EXPORT_UV, EXPORT_MTL,\ EXPORT_COPY_IMAGES, EXPORT_APPLY_MODIFIERS,\ EXPORT_ROTX90, EXPORT_BLEN_OBS,\ - EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_MORPH_TARGET) + EXPORT_GROUP_BY_OB, EXPORT_GROUP_BY_MAT, EXPORT_KEEP_VERT_ORDER) Blender.Set('curframe', orig_frame) diff --git a/release/scripts/import_obj.py b/release/scripts/import_obj.py index e5bdc796e16..b467cca112f 100644 --- a/release/scripts/import_obj.py +++ b/release/scripts/import_obj.py @@ -763,7 +763,7 @@ def load_obj_ui(filepath, BATCH_LOAD= False): SPLIT_OBJECTS= Draw.Create(1) SPLIT_GROUPS= Draw.Create(1) SPLIT_MATERIALS= Draw.Create(1) - MORPH_TARGET= Draw.Create(0) + KEEP_VERT_ORDER= Draw.Create(1) CLAMP_SIZE= Draw.Create(10.0) IMAGE_SEARCH= Draw.Create(1) @@ -779,7 +779,7 @@ def load_obj_ui(filepath, BATCH_LOAD= False): ('Group', SPLIT_GROUPS, 'Import OBJ Groups into Blender Objects'),\ ('Material', SPLIT_MATERIALS, 'Import each material into a seperate mesh (Avoids > 16 per mesh error)'),\ 'Options...',\ - ('Morph Target', MORPH_TARGET, 'Keep vert and face order, disables some other options.'),\ + ('Keep Vert Order', KEEP_VERT_ORDER, 'Keep vert and face order, disables some other options.'),\ ('Clamp Scale:', CLAMP_SIZE, 0.0, 1000.0, 'Clamp the size to this maximum (Zero to Disable)'),\ ('Image Search', IMAGE_SEARCH, 'Search subdirs for any assosiated images (Warning, may be slow)'),\ ] @@ -787,7 +787,7 @@ def load_obj_ui(filepath, BATCH_LOAD= False): if not Draw.PupBlock('Import OBJ...', pup_block): return - if MORPH_TARGET.val: + if KEEP_VERT_ORDER.val: SPLIT_OBJECTS.val = False SPLIT_GROUPS.val = False SPLIT_MATERIALS.val = False From bbdcd3a0828bf1e17d5e2ff9cf1a3b9c45c9d213 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 17 Sep 2008 11:23:28 +0000 Subject: [PATCH 109/125] rev 16569 broke building. Looks like bullets Extras/ConvexDecomposition is missing from blenders source. comment functions so it builds for now. --- extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp index d9919967233..900ab85497d 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp @@ -278,7 +278,7 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb, HullResult hres; HullLibrary hlib; hdsc.mMaxVertices=vertices.size(); - hlib.CreateConvexHull(hdsc,hres); + //hlib.CreateConvexHull(hdsc,hres); const btVector3 center=average(hres.m_OutputVertices); add(hres.m_OutputVertices,-center); mul(hres.m_OutputVertices,(btScalar)1); @@ -291,7 +291,7 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb, hres.m_OutputVertices[idx[2]], color,1); } - hlib.ReleaseResult(hres); + //hlib.ReleaseResult(hres); } /* Velocities */ #if 0 @@ -634,7 +634,7 @@ btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldI HullResult hres; HullLibrary hlib;/*??*/ hdsc.mMaxVertices=nvertices; - hlib.CreateConvexHull(hdsc,hres); + //hlib.CreateConvexHull(hdsc,hres); btSoftBody* psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices, &hres.m_OutputVertices[0],0); for(int i=0;i<(int)hres.mNumFaces;++i) @@ -647,7 +647,7 @@ btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldI if(idx[2]appendLink( idx[2],idx[0]); psb->appendFace(idx[0],idx[1],idx[2]); } - hlib.ReleaseResult(hres); + //hlib.ReleaseResult(hres); psb->randomizeConstraints(); return(psb); } From 2b6aea20093baaa1703ba320caedb83933f72f16 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 17 Sep 2008 11:31:03 +0000 Subject: [PATCH 110/125] Added BulletSoftBody as target for Makefile installing of .h files --- extern/bullet2/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extern/bullet2/Makefile b/extern/bullet2/Makefile index e05d441a6be..d26289c8b01 100644 --- a/extern/bullet2/Makefile +++ b/extern/bullet2/Makefile @@ -40,7 +40,8 @@ BulletCollision/NarrowPhaseCollision \ BulletCollision//CollisionDispatch \ BulletDynamics/ConstraintSolver \ BulletDynamics/Vehicle \ -BulletDynamics/Dynamics +BulletDynamics/Dynamics \ +BulletSoftBody include nan_subdirs.mk From b4e4ffc0b83a9e4f14d6d81dff424ff49e8f8c56 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 17 Sep 2008 16:59:52 +0000 Subject: [PATCH 111/125] Fix for bug #17634: crash on automatically removing zero size window. --- source/blender/src/editscreen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/src/editscreen.c b/source/blender/src/editscreen.c index 976e58ed102..2557894d0e0 100644 --- a/source/blender/src/editscreen.c +++ b/source/blender/src/editscreen.c @@ -1980,7 +1980,7 @@ static void testareas(void) /* test for header, if removed, or moved */ /* test for window, if removed, or moved */ - for(sa= G.curscreen->areabase.first; sa; sa= sa->next) { + for(sa= G.curscreen->areabase.first; sa; sa= next) { rcti oldhr= sa->headrct; rcti oldwr= sa->winrct; From 3ecbcb5848ced97621ab94fee86a5b6d415d5c17 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Wed, 17 Sep 2008 17:47:59 +0000 Subject: [PATCH 112/125] Bugfix #14412 Outliner option 'unlink group' didn't remove its members, in case the group members were local in file, a confusing situation happened. Now it removes members. --- source/blender/blenkernel/intern/group.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 2ffe8590b59..0d2f86bb151 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -91,6 +91,16 @@ void unlink_group(Group *group) ma->group= NULL; } for (sce= G.main->scene.first; sce; sce= sce->id.next) { + Base *base= sce->base.first; + + /* ensure objects are not in this group */ + for(; base; base= base->next) { + if(rem_from_group(group, base->object) && find_group(base->object, NULL)==NULL) { + base->object->flag &= ~OB_FROMGROUP; + base->flag &= ~OB_FROMGROUP; + } + } + for(srl= sce->r.layers.first; srl; srl= srl->next) { if (srl->light_override==group) srl->light_override= NULL; @@ -117,6 +127,9 @@ void unlink_group(Group *group) psys->part->eff_group= NULL; } } + + /* group stays in library, but no members */ + free_group(group); group->id.us= 0; } From 0a430367012dd7d2a71cb2ef3d743db3bd7787bd Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Wed, 17 Sep 2008 17:59:29 +0000 Subject: [PATCH 113/125] Fix for [#17637] Children from "Faces" in Object without a face leads to crash - a simple check for psys->child was missing --- source/blender/blenkernel/intern/particle_system.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index df193bc3802..3a93c0dab02 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1128,12 +1128,14 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm if(children){ if(G.f & G_DEBUG) fprintf(stderr,"Particle child distribution error: Nothing to emit from!\n"); - for(p=0,cpa=psys->child; pfuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]= 0.0; - cpa->foffset= 0.0f; - cpa->parent=0; - cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0; - cpa->num= -1; + if(psys->child) { + for(p=0,cpa=psys->child; pfuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]= 0.0; + cpa->foffset= 0.0f; + cpa->parent=0; + cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0; + cpa->num= -1; + } } } else { From 0a6d2e26a9eaeaf413c78e1f144fdcfe847fa317 Mon Sep 17 00:00:00 2001 From: Janne Karhu Date: Wed, 17 Sep 2008 19:29:44 +0000 Subject: [PATCH 114/125] Fix for [#17642] Particule Hair - Vertex Group lenght don't works without Children - This feature had been removed from the code! So this is how things work now: For normal (non-child) hair particles the length vgroup is used if we're not in particle edit mode and if there are no child particles. So for example checking "Parents" in the visualization panel when children are in use will result in full length parent strands, this is a feature so that you can see how the parent's go to predict child behavior better, not a bug :) --- source/blender/blenkernel/intern/particle.c | 62 ++++++++++++--------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 33af6037519..3ff57f55992 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -1775,37 +1775,17 @@ static void do_path_effectors(Object *ob, ParticleSystem *psys, int i, ParticleC static int check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *state, float max_length, float *cur_length, float length, float *dvec) { if(*cur_length + length > max_length){ - //if(ptime){ - // /* parents need to be calculated fully first so that they don't mess up their children */ - // /* we'll make a note of where we got to though so that they're easy to finish later */ - // state->time=(max_length-*cur_length)/length; - // cache[totpart+p]->time=(float)k; - // } - //} - //else{ VecMulf(dvec, (max_length - *cur_length) / length); VECADD(state->co, (state - 1)->co, dvec); keys->steps = k; /* something over the maximum step value */ return k=100000; - //} } else { *cur_length+=length; return k; } } -static void finalize_path_length(ParticleCacheKey *keys) -{ - ParticleCacheKey *state = keys; - float dvec[3]; - state += state->steps; - - VECSUB(dvec, state->co, (state - 1)->co); - VecMulf(dvec, state->steps); - VECADD(state->co, (state - 1)->co, dvec); -} static void offset_child(ChildParticle *cpa, ParticleKey *par, ParticleKey *child, float flat, float radius) { VECCOPY(child->co,cpa->fuv); @@ -1986,7 +1966,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey **cache= psys->childcache; ParticleCacheKey **pcache= psys->pathcache; ParticleCacheKey *state, *par = NULL, *key[4]; - ParticleData *pa; + ParticleData *pa=NULL; ParticleTexture ptex; float *cpa_fuv=0; float co[3], orco[3], ornor[3], t, rough_t, cpa_1st[3], dvec[3]; @@ -2287,10 +2267,6 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, get_strand_normal(ctx->ma, ornor, cur_length, state->vel); } } - - /* now let's finalise the interpolated parents that we might have left half done before */ - if(itotparent) - finalize_path_length(keys); } void *exec_child_path_cache(void *data) @@ -2364,6 +2340,7 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda ParticleCacheKey *ca, **cache=psys->pathcache; ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); ParticleEditSettings *pset = &G.scene->toolsettings->particle; + ParticleSettings *part = psys->part; ParticleData *pa; ParticleKey keys[4], result, *kkey[2] = {NULL, NULL}; @@ -2389,6 +2366,8 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda float nosel_col[3]; float length, vec[3]; float *vg_effector= NULL, effector=0.0f; + float *vg_length= NULL, pa_length=1.0f, max_length=1.0f, cur_length=0.0f; + float len, dvec[3]; /* we don't have anything valid to create paths from so let's quit here */ if((psys->flag & PSYS_HAIR_DONE)==0 && (psys->flag & PSYS_KEYED)==0) @@ -2440,6 +2419,9 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda if(psys->part->from!=PART_FROM_PARTICLE) { if(!(psys->part->flag & PART_CHILD_EFFECT)) vg_effector = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_EFFECTOR); + + if(!edit && !psys->totchild) + vg_length = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_LENGTH); } /*---first main loop: create all actual particles' paths---*/ @@ -2453,6 +2435,12 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda if(editupdate && !(pa->flag & PARS_EDIT_RECALC)) continue; else memset(cache[i], 0, sizeof(*cache[i])*(steps+1)); + if(!edit && !psys->totchild) { + pa_length = part->length * (1.0f - part->randlength*pa->r_ave[0]); + if(vg_length) + pa_length *= psys_interpolate_value_from_verts(psmd->dm,part->from,pa->num,pa->fuv,vg_length); + } + cache[i]->steps = steps; if(edit) @@ -2678,6 +2666,27 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda } + if(!edit && !psys->totchild) { + /* check if path needs to be cut before actual end of data points */ + if(k){ + VECSUB(dvec,ca->co,(ca-1)->co); + if(part->flag&PART_ABS_LENGTH) + len=VecLength(dvec); + else + len=1.0f/(float)steps; + + k=check_path_length(k,cache[i],ca,max_length,&cur_length,len,dvec); + } + else{ + /* initialize length calculation */ + if(part->flag&PART_ABS_LENGTH) + max_length= part->abslength*pa_length; + else + max_length= pa_length; + + cur_length= 0.0f; + } + } } } @@ -2690,6 +2699,9 @@ void psys_cache_paths(Object *ob, ParticleSystem *psys, float cfra, int editupda if(vg_effector) MEM_freeN(vg_effector); + + if(vg_length) + MEM_freeN(vg_length); } /************************************************/ /* Particle Key handling */ From 015a42079c299f4256240dc347de8ccfa474514a Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Wed, 17 Sep 2008 19:47:26 +0000 Subject: [PATCH 115/125] Please add extern/bullet2/src/LinearMath/btConvexHull.cpp to your build system! Reverted back to original Bullet version. --- extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp index 900ab85497d..d9919967233 100644 --- a/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp +++ b/extern/bullet2/src/BulletSoftBody/btSoftBodyHelpers.cpp @@ -278,7 +278,7 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb, HullResult hres; HullLibrary hlib; hdsc.mMaxVertices=vertices.size(); - //hlib.CreateConvexHull(hdsc,hres); + hlib.CreateConvexHull(hdsc,hres); const btVector3 center=average(hres.m_OutputVertices); add(hres.m_OutputVertices,-center); mul(hres.m_OutputVertices,(btScalar)1); @@ -291,7 +291,7 @@ void btSoftBodyHelpers::Draw( btSoftBody* psb, hres.m_OutputVertices[idx[2]], color,1); } - //hlib.ReleaseResult(hres); + hlib.ReleaseResult(hres); } /* Velocities */ #if 0 @@ -634,7 +634,7 @@ btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldI HullResult hres; HullLibrary hlib;/*??*/ hdsc.mMaxVertices=nvertices; - //hlib.CreateConvexHull(hdsc,hres); + hlib.CreateConvexHull(hdsc,hres); btSoftBody* psb=new btSoftBody(&worldInfo,(int)hres.mNumOutputVertices, &hres.m_OutputVertices[0],0); for(int i=0;i<(int)hres.mNumFaces;++i) @@ -647,7 +647,7 @@ btSoftBody* btSoftBodyHelpers::CreateFromConvexHull(btSoftBodyWorldInfo& worldI if(idx[2]appendLink( idx[2],idx[0]); psb->appendFace(idx[0],idx[1],idx[2]); } - //hlib.ReleaseResult(hres); + hlib.ReleaseResult(hres); psb->randomizeConstraints(); return(psb); } From 8b73f35141c2572c123791029b58c438d6d5fb9f Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Wed, 17 Sep 2008 19:58:16 +0000 Subject: [PATCH 116/125] added src/LinearMath/btConvexHull.cpp --- .../bullet2/src/LinearMath/btConvexHull.cpp | 1153 +++++++++++++++++ 1 file changed, 1153 insertions(+) create mode 100644 extern/bullet2/src/LinearMath/btConvexHull.cpp diff --git a/extern/bullet2/src/LinearMath/btConvexHull.cpp b/extern/bullet2/src/LinearMath/btConvexHull.cpp new file mode 100644 index 00000000000..a20b2059ae9 --- /dev/null +++ b/extern/bullet2/src/LinearMath/btConvexHull.cpp @@ -0,0 +1,1153 @@ +/* +Stan Melax Convex Hull Computation +Copyright (c) 2003-2006 Stan Melax http://www.melax.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 + +#include "btConvexHull.h" +#include "LinearMath/btAlignedObjectArray.h" +#include "LinearMath/btMinMax.h" +#include "LinearMath/btVector3.h" + + + +template +void Swap(T &a,T &b) +{ + T tmp = a; + a=b; + b=tmp; +} + + +//---------------------------------- + +class int3 +{ +public: + int x,y,z; + int3(){}; + int3(int _x,int _y, int _z){x=_x;y=_y;z=_z;} + const int& operator[](int i) const {return (&x)[i];} + int& operator[](int i) {return (&x)[i];} +}; + + +//------- btPlane ---------- + + +inline btPlane PlaneFlip(const btPlane &plane){return btPlane(-plane.normal,-plane.dist);} +inline int operator==( const btPlane &a, const btPlane &b ) { return (a.normal==b.normal && a.dist==b.dist); } +inline int coplanar( const btPlane &a, const btPlane &b ) { return (a==b || a==PlaneFlip(b)); } + + +//--------- Utility Functions ------ + +btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1); +btVector3 PlaneProject(const btPlane &plane, const btVector3 &point); + +btVector3 ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2); +btVector3 ThreePlaneIntersection(const btPlane &p0,const btPlane &p1, const btPlane &p2) +{ + btVector3 N1 = p0.normal; + btVector3 N2 = p1.normal; + btVector3 N3 = p2.normal; + + btVector3 n2n3; n2n3 = N2.cross(N3); + btVector3 n3n1; n3n1 = N3.cross(N1); + btVector3 n1n2; n1n2 = N1.cross(N2); + + btScalar quotient = (N1.dot(n2n3)); + + btAssert(btFabs(quotient) > btScalar(0.000001)); + + quotient = btScalar(-1.) / quotient; + n2n3 *= p0.dist; + n3n1 *= p1.dist; + n1n2 *= p2.dist; + btVector3 potentialVertex = n2n3; + potentialVertex += n3n1; + potentialVertex += n1n2; + potentialVertex *= quotient; + + btVector3 result(potentialVertex.getX(),potentialVertex.getY(),potentialVertex.getZ()); + return result; + +} + +btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint=NULL, btVector3 *vpoint=NULL); +btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2); +btVector3 NormalOf(const btVector3 *vert, const int n); + + +btVector3 PlaneLineIntersection(const btPlane &plane, const btVector3 &p0, const btVector3 &p1) +{ + // returns the point where the line p0-p1 intersects the plane n&d + static btVector3 dif; + dif = p1-p0; + btScalar dn= dot(plane.normal,dif); + btScalar t = -(plane.dist+dot(plane.normal,p0) )/dn; + return p0 + (dif*t); +} + +btVector3 PlaneProject(const btPlane &plane, const btVector3 &point) +{ + return point - plane.normal * (dot(point,plane.normal)+plane.dist); +} + +btVector3 TriNormal(const btVector3 &v0, const btVector3 &v1, const btVector3 &v2) +{ + // return the normal of the triangle + // inscribed by v0, v1, and v2 + btVector3 cp=cross(v1-v0,v2-v1); + btScalar m=cp.length(); + if(m==0) return btVector3(1,0,0); + return cp*(btScalar(1.0)/m); +} + + +btScalar DistanceBetweenLines(const btVector3 &ustart, const btVector3 &udir, const btVector3 &vstart, const btVector3 &vdir, btVector3 *upoint, btVector3 *vpoint) +{ + static btVector3 cp; + cp = cross(udir,vdir).normalized(); + + btScalar distu = -dot(cp,ustart); + btScalar distv = -dot(cp,vstart); + btScalar dist = (btScalar)fabs(distu-distv); + if(upoint) + { + btPlane plane; + plane.normal = cross(vdir,cp).normalized(); + plane.dist = -dot(plane.normal,vstart); + *upoint = PlaneLineIntersection(plane,ustart,ustart+udir); + } + if(vpoint) + { + btPlane plane; + plane.normal = cross(udir,cp).normalized(); + plane.dist = -dot(plane.normal,ustart); + *vpoint = PlaneLineIntersection(plane,vstart,vstart+vdir); + } + return dist; +} + + + + + + + +#define COPLANAR (0) +#define UNDER (1) +#define OVER (2) +#define SPLIT (OVER|UNDER) +#define PAPERWIDTH (btScalar(0.001)) + +btScalar planetestepsilon = PAPERWIDTH; + + + +typedef ConvexH::HalfEdge HalfEdge; + +ConvexH::ConvexH(int vertices_size,int edges_size,int facets_size) +{ + vertices.resize(vertices_size); + edges.resize(edges_size); + facets.resize(facets_size); +} + + +int PlaneTest(const btPlane &p, const btVector3 &v); +int PlaneTest(const btPlane &p, const btVector3 &v) { + btScalar a = dot(v,p.normal)+p.dist; + int flag = (a>planetestepsilon)?OVER:((a<-planetestepsilon)?UNDER:COPLANAR); + return flag; +} + +int SplitTest(ConvexH &convex,const btPlane &plane); +int SplitTest(ConvexH &convex,const btPlane &plane) { + int flag=0; + for(int i=0;i +int maxdirfiltered(const T *p,int count,const T &dir,btAlignedObjectArray &allow) +{ + btAssert(count); + int m=-1; + for(int i=0;idot(p[m],dir)) + m=i; + } + btAssert(m!=-1); + return m; +} + +btVector3 orth(const btVector3 &v); +btVector3 orth(const btVector3 &v) +{ + btVector3 a=cross(v,btVector3(0,0,1)); + btVector3 b=cross(v,btVector3(0,1,0)); + if (a.length() > b.length()) + { + return a.normalized(); + } else { + return b.normalized(); + } +} + + +template +int maxdirsterid(const T *p,int count,const T &dir,btAlignedObjectArray &allow) +{ + int m=-1; + while(m==-1) + { + m = maxdirfiltered(p,count,dir,allow); + if(allow[m]==3) return m; + T u = orth(dir); + T v = cross(u,dir); + int ma=-1; + for(btScalar x = btScalar(0.0) ; x<= btScalar(360.0) ; x+= btScalar(45.0)) + { + btScalar s = sinf(SIMD_RADS_PER_DEG*(x)); + btScalar c = cosf(SIMD_RADS_PER_DEG*(x)); + int mb = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow); + if(ma==m && mb==m) + { + allow[m]=3; + return m; + } + if(ma!=-1 && ma!=mb) // Yuck - this is really ugly + { + int mc = ma; + for(btScalar xx = x-btScalar(40.0) ; xx <= x ; xx+= btScalar(5.0)) + { + btScalar s = sinf(SIMD_RADS_PER_DEG*(xx)); + btScalar c = cosf(SIMD_RADS_PER_DEG*(xx)); + int md = maxdirfiltered(p,count,dir+(u*s+v*c)*btScalar(0.025),allow); + if(mc==m && md==m) + { + allow[m]=3; + return m; + } + mc=md; + } + } + ma=mb; + } + allow[m]=0; + m=-1; + } + btAssert(0); + return m; +} + + + + +int operator ==(const int3 &a,const int3 &b); +int operator ==(const int3 &a,const int3 &b) +{ + for(int i=0;i<3;i++) + { + if(a[i]!=b[i]) return 0; + } + return 1; +} + + +int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon); +int above(btVector3* vertices,const int3& t, const btVector3 &p, btScalar epsilon) +{ + btVector3 n=TriNormal(vertices[t[0]],vertices[t[1]],vertices[t[2]]); + return (dot(n,p-vertices[t[0]]) > epsilon); // EPSILON??? +} +int hasedge(const int3 &t, int a,int b); +int hasedge(const int3 &t, int a,int b) +{ + for(int i=0;i<3;i++) + { + int i1= (i+1)%3; + if(t[i]==a && t[i1]==b) return 1; + } + return 0; +} +int hasvert(const int3 &t, int v); +int hasvert(const int3 &t, int v) +{ + return (t[0]==v || t[1]==v || t[2]==v) ; +} +int shareedge(const int3 &a,const int3 &b); +int shareedge(const int3 &a,const int3 &b) +{ + int i; + for(i=0;i<3;i++) + { + int i1= (i+1)%3; + if(hasedge(a,b[i1],b[i])) return 1; + } + return 0; +} + +class Tri; + + + +class Tri : public int3 +{ +public: + int3 n; + int id; + int vmax; + btScalar rise; + Tri(int a,int b,int c):int3(a,b,c),n(-1,-1,-1) + { + vmax=-1; + rise = btScalar(0.0); + } + ~Tri() + { + } + int &neib(int a,int b); +}; + + +int &Tri::neib(int a,int b) +{ + static int er=-1; + int i; + for(i=0;i<3;i++) + { + int i1=(i+1)%3; + int i2=(i+2)%3; + if((*this)[i]==a && (*this)[i1]==b) return n[i2]; + if((*this)[i]==b && (*this)[i1]==a) return n[i2]; + } + btAssert(0); + return er; +} +void HullLibrary::b2bfix(Tri* s,Tri*t) +{ + int i; + for(i=0;i<3;i++) + { + int i1=(i+1)%3; + int i2=(i+2)%3; + int a = (*s)[i1]; + int b = (*s)[i2]; + btAssert(m_tris[s->neib(a,b)]->neib(b,a) == s->id); + btAssert(m_tris[t->neib(a,b)]->neib(b,a) == t->id); + m_tris[s->neib(a,b)]->neib(b,a) = t->neib(b,a); + m_tris[t->neib(b,a)]->neib(a,b) = s->neib(a,b); + } +} + +void HullLibrary::removeb2b(Tri* s,Tri*t) +{ + b2bfix(s,t); + deAllocateTriangle(s); + + deAllocateTriangle(t); +} + +void HullLibrary::checkit(Tri *t) +{ + (void)t; + + int i; + btAssert(m_tris[t->id]==t); + for(i=0;i<3;i++) + { + int i1=(i+1)%3; + int i2=(i+2)%3; + int a = (*t)[i1]; + int b = (*t)[i2]; + + // release compile fix + (void)i1; + (void)i2; + (void)a; + (void)b; + + btAssert(a!=b); + btAssert( m_tris[t->n[i]]->neib(b,a) == t->id); + } +} + +Tri* HullLibrary::allocateTriangle(int a,int b,int c) +{ + void* mem = btAlignedAlloc(sizeof(Tri),16); + Tri* tr = new (mem)Tri(a,b,c); + tr->id = m_tris.size(); + m_tris.push_back(tr); + + return tr; +} + +void HullLibrary::deAllocateTriangle(Tri* tri) +{ + btAssert(m_tris[tri->id]==tri); + m_tris[tri->id]=NULL; + tri->~Tri(); + btAlignedFree(tri); +} + + +void HullLibrary::extrude(Tri *t0,int v) +{ + int3 t= *t0; + int n = m_tris.size(); + Tri* ta = allocateTriangle(v,t[1],t[2]); + ta->n = int3(t0->n[0],n+1,n+2); + m_tris[t0->n[0]]->neib(t[1],t[2]) = n+0; + Tri* tb = allocateTriangle(v,t[2],t[0]); + tb->n = int3(t0->n[1],n+2,n+0); + m_tris[t0->n[1]]->neib(t[2],t[0]) = n+1; + Tri* tc = allocateTriangle(v,t[0],t[1]); + tc->n = int3(t0->n[2],n+0,n+1); + m_tris[t0->n[2]]->neib(t[0],t[1]) = n+2; + checkit(ta); + checkit(tb); + checkit(tc); + if(hasvert(*m_tris[ta->n[0]],v)) removeb2b(ta,m_tris[ta->n[0]]); + if(hasvert(*m_tris[tb->n[0]],v)) removeb2b(tb,m_tris[tb->n[0]]); + if(hasvert(*m_tris[tc->n[0]],v)) removeb2b(tc,m_tris[tc->n[0]]); + deAllocateTriangle(t0); + +} + +Tri* HullLibrary::extrudable(btScalar epsilon) +{ + int i; + Tri *t=NULL; + for(i=0;iriserise)) + { + t = m_tris[i]; + } + } + return (t->rise >epsilon)?t:NULL ; +} + + + + +int4 HullLibrary::FindSimplex(btVector3 *verts,int verts_count,btAlignedObjectArray &allow) +{ + btVector3 basis[3]; + basis[0] = btVector3( btScalar(0.01), btScalar(0.02), btScalar(1.0) ); + int p0 = maxdirsterid(verts,verts_count, basis[0],allow); + int p1 = maxdirsterid(verts,verts_count,-basis[0],allow); + basis[0] = verts[p0]-verts[p1]; + if(p0==p1 || basis[0]==btVector3(0,0,0)) + return int4(-1,-1,-1,-1); + basis[1] = cross(btVector3( btScalar(1),btScalar(0.02), btScalar(0)),basis[0]); + basis[2] = cross(btVector3(btScalar(-0.02), btScalar(1), btScalar(0)),basis[0]); + if (basis[1].length() > basis[2].length()) + { + basis[1].normalize(); + } else { + basis[1] = basis[2]; + basis[1].normalize (); + } + int p2 = maxdirsterid(verts,verts_count,basis[1],allow); + if(p2 == p0 || p2 == p1) + { + p2 = maxdirsterid(verts,verts_count,-basis[1],allow); + } + if(p2 == p0 || p2 == p1) + return int4(-1,-1,-1,-1); + basis[1] = verts[p2] - verts[p0]; + basis[2] = cross(basis[1],basis[0]).normalized(); + int p3 = maxdirsterid(verts,verts_count,basis[2],allow); + if(p3==p0||p3==p1||p3==p2) p3 = maxdirsterid(verts,verts_count,-basis[2],allow); + if(p3==p0||p3==p1||p3==p2) + return int4(-1,-1,-1,-1); + btAssert(!(p0==p1||p0==p2||p0==p3||p1==p2||p1==p3||p2==p3)); + if(dot(verts[p3]-verts[p0],cross(verts[p1]-verts[p0],verts[p2]-verts[p0])) <0) {Swap(p2,p3);} + return int4(p0,p1,p2,p3); +} + +int HullLibrary::calchullgen(btVector3 *verts,int verts_count, int vlimit) +{ + if(verts_count <4) return 0; + if(vlimit==0) vlimit=1000000000; + int j; + btVector3 bmin(*verts),bmax(*verts); + btAlignedObjectArray isextreme; + isextreme.reserve(verts_count); + btAlignedObjectArray allow; + allow.reserve(verts_count); + + for(j=0;jn=int3(2,3,1); + Tri *t1 = allocateTriangle(p[3],p[2],p[0]); t1->n=int3(3,2,0); + Tri *t2 = allocateTriangle(p[0],p[1],p[3]); t2->n=int3(0,1,3); + Tri *t3 = allocateTriangle(p[1],p[0],p[2]); t3->n=int3(1,0,2); + isextreme[p[0]]=isextreme[p[1]]=isextreme[p[2]]=isextreme[p[3]]=1; + checkit(t0);checkit(t1);checkit(t2);checkit(t3); + + for(j=0;jvmax<0); + btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]); + t->vmax = maxdirsterid(verts,verts_count,n,allow); + t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]); + } + Tri *te; + vlimit-=4; + while(vlimit >0 && ((te=extrudable(epsilon)) != 0)) + { + int3 ti=*te; + int v=te->vmax; + btAssert(v != -1); + btAssert(!isextreme[v]); // wtf we've already done this vertex + isextreme[v]=1; + //if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already + j=m_tris.size(); + while(j--) { + if(!m_tris[j]) continue; + int3 t=*m_tris[j]; + if(above(verts,t,verts[v],btScalar(0.01)*epsilon)) + { + extrude(m_tris[j],v); + } + } + // now check for those degenerate cases where we have a flipped triangle or a really skinny triangle + j=m_tris.size(); + while(j--) + { + if(!m_tris[j]) continue; + if(!hasvert(*m_tris[j],v)) break; + int3 nt=*m_tris[j]; + if(above(verts,nt,center,btScalar(0.01)*epsilon) || cross(verts[nt[1]]-verts[nt[0]],verts[nt[2]]-verts[nt[1]]).length()< epsilon*epsilon*btScalar(0.1) ) + { + Tri *nb = m_tris[m_tris[j]->n[0]]; + btAssert(nb);btAssert(!hasvert(*nb,v));btAssert(nb->idvmax>=0) break; + btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]); + t->vmax = maxdirsterid(verts,verts_count,n,allow); + if(isextreme[t->vmax]) + { + t->vmax=-1; // already done that vertex - algorithm needs to be able to terminate. + } + else + { + t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]); + } + } + vlimit --; + } + return 1; +} + +int HullLibrary::calchull(btVector3 *verts,int verts_count, TUIntArray& tris_out, int &tris_count,int vlimit) +{ + int rc=calchullgen(verts,verts_count, vlimit) ; + if(!rc) return 0; + btAlignedObjectArray ts; + int i; + + for(i=0;i(ts[i]); + } + m_tris.resize(0); + + return 1; +} + + + + + +bool HullLibrary::ComputeHull(unsigned int vcount,const btVector3 *vertices,PHullResult &result,unsigned int vlimit) +{ + + int tris_count; + int ret = calchull( (btVector3 *) vertices, (int) vcount, result.m_Indices, tris_count, static_cast(vlimit) ); + if(!ret) return false; + result.mIndexCount = (unsigned int) (tris_count*3); + result.mFaceCount = (unsigned int) tris_count; + result.mVertices = (btVector3*) vertices; + result.mVcount = (unsigned int) vcount; + return true; + +} + + +void ReleaseHull(PHullResult &result); +void ReleaseHull(PHullResult &result) +{ + if ( result.m_Indices.size() ) + { + result.m_Indices.clear(); + } + + result.mVcount = 0; + result.mIndexCount = 0; + result.mVertices = 0; +} + + +//********************************************************************* +//********************************************************************* +//******** HullLib header +//********************************************************************* +//********************************************************************* + +//********************************************************************* +//********************************************************************* +//******** HullLib implementation +//********************************************************************* +//********************************************************************* + +HullError HullLibrary::CreateConvexHull(const HullDesc &desc, // describes the input request + HullResult &result) // contains the resulst +{ + HullError ret = QE_FAIL; + + + PHullResult hr; + + unsigned int vcount = desc.mVcount; + if ( vcount < 8 ) vcount = 8; + + btAlignedObjectArray vertexSource; + vertexSource.resize(static_cast(vcount)); + + btVector3 scale; + + unsigned int ovcount; + + bool ok = CleanupVertices(desc.mVcount,desc.mVertices, desc.mVertexStride, ovcount, &vertexSource[0], desc.mNormalEpsilon, scale ); // normalize point cloud, remove duplicates! + + if ( ok ) + { + + +// if ( 1 ) // scale vertices back to their original size. + { + for (unsigned int i=0; i(i)]; + v[0]*=scale[0]; + v[1]*=scale[1]; + v[2]*=scale[2]; + } + } + + ok = ComputeHull(ovcount,&vertexSource[0],hr,desc.mMaxVertices); + + if ( ok ) + { + + // re-index triangle mesh so it refers to only used vertices, rebuild a new vertex table. + btAlignedObjectArray vertexScratch; + vertexScratch.resize(static_cast(hr.mVcount)); + + BringOutYourDead(hr.mVertices,hr.mVcount, &vertexScratch[0], ovcount, &hr.m_Indices[0], hr.mIndexCount ); + + ret = QE_OK; + + if ( desc.HasHullFlag(QF_TRIANGLES) ) // if he wants the results as triangle! + { + result.mPolygons = false; + result.mNumOutputVertices = ovcount; + result.m_OutputVertices.resize(static_cast(ovcount)); + result.mNumFaces = hr.mFaceCount; + result.mNumIndices = hr.mIndexCount; + + result.m_Indices.resize(static_cast(hr.mIndexCount)); + + memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount ); + + if ( desc.HasHullFlag(QF_REVERSE_ORDER) ) + { + + const unsigned int *source = &hr.m_Indices[0]; + unsigned int *dest = &result.m_Indices[0]; + + for (unsigned int i=0; i(ovcount)); + result.mNumFaces = hr.mFaceCount; + result.mNumIndices = hr.mIndexCount+hr.mFaceCount; + result.m_Indices.resize(static_cast(result.mNumIndices)); + memcpy(&result.m_OutputVertices[0], &vertexScratch[0], sizeof(btVector3)*ovcount ); + +// if ( 1 ) + { + const unsigned int *source = &hr.m_Indices[0]; + unsigned int *dest = &result.m_Indices[0]; + for (unsigned int i=0; i bmax[j] ) bmax[j] = p[j]; + } + } + } + + btScalar dx = bmax[0] - bmin[0]; + btScalar dy = bmax[1] - bmin[1]; + btScalar dz = bmax[2] - bmin[2]; + + btVector3 center; + + center[0] = dx*btScalar(0.5) + bmin[0]; + center[1] = dy*btScalar(0.5) + bmin[1]; + center[2] = dz*btScalar(0.5) + bmin[2]; + + if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || svcount < 3 ) + { + + btScalar len = FLT_MAX; + + if ( dx > EPSILON && dx < len ) len = dx; + if ( dy > EPSILON && dy < len ) len = dy; + if ( dz > EPSILON && dz < len ) len = dz; + + if ( len == FLT_MAX ) + { + dx = dy = dz = btScalar(0.01); // one centimeter + } + else + { + if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge. + if ( dy < EPSILON ) dy = len * btScalar(0.05); + if ( dz < EPSILON ) dz = len * btScalar(0.05); + } + + btScalar x1 = center[0] - dx; + btScalar x2 = center[0] + dx; + + btScalar y1 = center[1] - dy; + btScalar y2 = center[1] + dy; + + btScalar z1 = center[2] - dz; + btScalar z2 = center[2] + dz; + + addPoint(vcount,vertices,x1,y1,z1); + addPoint(vcount,vertices,x2,y1,z1); + addPoint(vcount,vertices,x2,y2,z1); + addPoint(vcount,vertices,x1,y2,z1); + addPoint(vcount,vertices,x1,y1,z2); + addPoint(vcount,vertices,x2,y1,z2); + addPoint(vcount,vertices,x2,y2,z2); + addPoint(vcount,vertices,x1,y2,z2); + + return true; // return cube + + + } + else + { + if ( scale ) + { + scale[0] = dx; + scale[1] = dy; + scale[2] = dz; + + recip[0] = 1 / dx; + recip[1] = 1 / dy; + recip[2] = 1 / dz; + + center[0]*=recip[0]; + center[1]*=recip[1]; + center[2]*=recip[2]; + + } + + } + + + + vtx = (const char *) svertices; + + for (unsigned int i=0; igetX(); + btScalar py = p->getY(); + btScalar pz = p->getZ(); + + if ( scale ) + { + px = px*recip[0]; // normalize + py = py*recip[1]; // normalize + pz = pz*recip[2]; // normalize + } + +// if ( 1 ) + { + unsigned int j; + + for (j=0; j dist2 ) + { + v[0] = px; + v[1] = py; + v[2] = pz; + } + + break; + } + } + + if ( j == vcount ) + { + btVector3& dest = vertices[vcount]; + dest[0] = px; + dest[1] = py; + dest[2] = pz; + vcount++; + } + } + } + + // ok..now make sure we didn't prune so many vertices it is now invalid. +// if ( 1 ) + { + btScalar bmin[3] = { FLT_MAX, FLT_MAX, FLT_MAX }; + btScalar bmax[3] = { -FLT_MAX, -FLT_MAX, -FLT_MAX }; + + for (unsigned int i=0; i bmax[j] ) bmax[j] = p[j]; + } + } + + btScalar dx = bmax[0] - bmin[0]; + btScalar dy = bmax[1] - bmin[1]; + btScalar dz = bmax[2] - bmin[2]; + + if ( dx < EPSILON || dy < EPSILON || dz < EPSILON || vcount < 3) + { + btScalar cx = dx*btScalar(0.5) + bmin[0]; + btScalar cy = dy*btScalar(0.5) + bmin[1]; + btScalar cz = dz*btScalar(0.5) + bmin[2]; + + btScalar len = FLT_MAX; + + if ( dx >= EPSILON && dx < len ) len = dx; + if ( dy >= EPSILON && dy < len ) len = dy; + if ( dz >= EPSILON && dz < len ) len = dz; + + if ( len == FLT_MAX ) + { + dx = dy = dz = btScalar(0.01); // one centimeter + } + else + { + if ( dx < EPSILON ) dx = len * btScalar(0.05); // 1/5th the shortest non-zero edge. + if ( dy < EPSILON ) dy = len * btScalar(0.05); + if ( dz < EPSILON ) dz = len * btScalar(0.05); + } + + btScalar x1 = cx - dx; + btScalar x2 = cx + dx; + + btScalar y1 = cy - dy; + btScalar y2 = cy + dy; + + btScalar z1 = cz - dz; + btScalar z2 = cz + dz; + + vcount = 0; // add box + + addPoint(vcount,vertices,x1,y1,z1); + addPoint(vcount,vertices,x2,y1,z1); + addPoint(vcount,vertices,x2,y2,z1); + addPoint(vcount,vertices,x1,y2,z1); + addPoint(vcount,vertices,x1,y1,z2); + addPoint(vcount,vertices,x2,y1,z2); + addPoint(vcount,vertices,x2,y2,z2); + addPoint(vcount,vertices,x1,y2,z2); + + return true; + } + } + + return true; +} + +void HullLibrary::BringOutYourDead(const btVector3* verts,unsigned int vcount, btVector3* overts,unsigned int &ocount,unsigned int *indices,unsigned indexcount) +{ + TUIntArray usedIndices; + usedIndices.resize(static_cast(vcount)); + memset(&usedIndices[0],0,sizeof(unsigned int)*vcount); + + ocount = 0; + + for (unsigned int i=0; i= 0 && v < vcount ); + + if ( usedIndices[static_cast(v)] ) // if already remapped + { + indices[i] = usedIndices[static_cast(v)]-1; // index to new array + } + else + { + + indices[i] = ocount; // new index mapping + + overts[ocount][0] = verts[v][0]; // copy old vert to new vert array + overts[ocount][1] = verts[v][1]; + overts[ocount][2] = verts[v][2]; + + ocount++; // increment output vert count + + btAssert( ocount >=0 && ocount <= vcount ); + + usedIndices[static_cast(v)] = ocount; // assign new index remapping + } + } + + +} From 80f22a9e602c40eca5c7f8a9a7b5b8b291b51bff Mon Sep 17 00:00:00 2001 From: Erwin Coumans Date: Wed, 17 Sep 2008 20:02:20 +0000 Subject: [PATCH 117/125] added another missing file, btHashMap --- extern/bullet2/src/LinearMath/btHashMap.h | 303 ++++++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 extern/bullet2/src/LinearMath/btHashMap.h diff --git a/extern/bullet2/src/LinearMath/btHashMap.h b/extern/bullet2/src/LinearMath/btHashMap.h new file mode 100644 index 00000000000..f883e0e489a --- /dev/null +++ b/extern/bullet2/src/LinearMath/btHashMap.h @@ -0,0 +1,303 @@ +#ifndef BT_HASH_MAP_H +#define BT_HASH_MAP_H + +#include "btAlignedObjectArray.h" + +const int BT_HASH_NULL=0xffffffff; + +template +class btHashKey +{ + int m_uid; +public: + + btHashKey(int uid) + :m_uid(uid) + { + } + + int getUid() const + { + return m_uid; + } + + //to our success + SIMD_FORCE_INLINE unsigned int getHash()const + { + int key = m_uid; + // Thomas Wang's hash + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; + } + + btHashKey getKey(const Value& value) const + { + return btHashKey(value.getUid()); + } +}; + + +template +class btHashKeyPtr +{ + int m_uid; +public: + + btHashKeyPtr(int uid) + :m_uid(uid) + { + } + + int getUid() const + { + return m_uid; + } + + //to our success + SIMD_FORCE_INLINE unsigned int getHash()const + { + int key = m_uid; + // Thomas Wang's hash + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; + } + + btHashKeyPtr getKey(const Value& value) const + { + return btHashKeyPtr(value->getUid()); + } +}; + +///The btHashMap template class implements a generic and lightweight hashmap. +///A basic sample of how to use btHashMap is located in Demos\BasicDemo\main.cpp +template +class btHashMap +{ + + btAlignedObjectArray m_hashTable; + btAlignedObjectArray m_next; + btAlignedObjectArray m_valueArray; + + + + void growTables(const Key& key) + { + int newCapacity = m_valueArray.capacity(); + + if (m_hashTable.size() < newCapacity) + { + //grow hashtable and next table + int curHashtableSize = m_hashTable.size(); + + m_hashTable.resize(newCapacity); + m_next.resize(newCapacity); + + int i; + + for (i= 0; i < newCapacity; ++i) + { + m_hashTable[i] = BT_HASH_NULL; + } + for (i = 0; i < newCapacity; ++i) + { + m_next[i] = BT_HASH_NULL; + } + + for(i=0;i= m_hashTable.size()) + { + return BT_HASH_NULL; + } + + int index = m_hashTable[hash]; + while ((index != BT_HASH_NULL) && (key.getUid() == key.getKey(m_valueArray[index]).getUid()) == false) + { + index = m_next[index]; + } + return index; + } + + void clear() + { + m_hashTable.clear(); + m_next.clear(); + m_valueArray.clear(); + } + +}; + +#endif //BT_HASH_MAP_H From 0c1ec934c61ae65585bc8d317276da8484dddabc Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Wed, 17 Sep 2008 21:14:48 +0000 Subject: [PATCH 118/125] Update MSVC project file to include BulletSoftBody --- .../bullet2/make/msvc_7_0/Bullet_vc7.vcproj | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj index 7a6b58b2ed7..be4f78102a4 100644 --- a/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj +++ b/extern/bullet2/make/msvc_7_0/Bullet_vc7.vcproj @@ -58,9 +58,11 @@ IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\C IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\Dynamics MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Dynamics IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletDynamics\Vehicle MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletDynamics\Vehicle IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\LinearMath MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\LinearMath +IF NOT EXIST ..\..\..\..\..\build\msvc_7\extern\bullet2\include\BulletSoftBody MKDIR ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletSoftBody XCOPY /Y ..\..\src\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include XCOPY /Y ..\..\src\LinearMath\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\LinearMath +XCOPY /Y ..\..\src\BulletSoftBody\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletSoftBody XCOPY /Y ..\..\src\BulletCollision\BroadphaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\BroadphaseCollision XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision XCOPY /Y ..\..\src\BulletCollision\NarrowPhaseCollision\*.h ..\..\..\..\..\build\msvc_7\extern\bullet\include\BulletCollision\NarrowPhaseCollision @@ -976,6 +978,9 @@ ECHO Done + + @@ -988,6 +993,9 @@ ECHO Done + + @@ -1040,6 +1048,58 @@ ECHO Done RelativePath="..\..\src\LinearMath\btVector3.h"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 067a890d823bb0181b1d028931004eba86fb9220 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Wed, 17 Sep 2008 21:47:05 +0000 Subject: [PATCH 119/125] BGE bug #17578: repair linV actuator in Add+Local mode. --- source/gameengine/Ketsji/KX_GameObject.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 0e5956d4fdb..252741754ec 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -590,8 +590,11 @@ KX_GameObject::GetLayer( void KX_GameObject::addLinearVelocity(const MT_Vector3& lin_vel,bool local) { - if (m_pPhysicsController1) - m_pPhysicsController1->SetLinearVelocity(lin_vel + m_pPhysicsController1->GetLinearVelocity(),local); + if (m_pPhysicsController1) + { + MT_Vector3 lv = local ? NodeGetWorldOrientation() * lin_vel : lin_vel; + m_pPhysicsController1->SetLinearVelocity(lv + m_pPhysicsController1->GetLinearVelocity(), 0); + } } From 7e6c1e1091b51dfdaad19ee4b8e1651b10e02057 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 18 Sep 2008 00:10:12 +0000 Subject: [PATCH 120/125] needed these changes to get bullet building with cmake and linking with scons --- extern/bullet2/src/CMakeLists.txt | 2 +- extern/bullet2/src/SConscript | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extern/bullet2/src/CMakeLists.txt b/extern/bullet2/src/CMakeLists.txt index 0ae1a7ab6ab..043fd3f6e7f 100644 --- a/extern/bullet2/src/CMakeLists.txt +++ b/extern/bullet2/src/CMakeLists.txt @@ -1 +1 @@ -SUBDIRS( BulletCollision BulletDynamics LinearMath ) +SUBDIRS( BulletCollision BulletDynamics LinearMath BulletSoftBody ) diff --git a/extern/bullet2/src/SConscript b/extern/bullet2/src/SConscript index b2ec67984d3..77d94bc8dab 100644 --- a/extern/bullet2/src/SConscript +++ b/extern/bullet2/src/SConscript @@ -35,4 +35,4 @@ 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_bullet2softbody', sources=softbody_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 ) From 3bf0a6fed88e43605fa82acbd1dbad7e64bed93d Mon Sep 17 00:00:00 2001 From: Matt Ebb Date: Thu, 18 Sep 2008 00:51:51 +0000 Subject: [PATCH 121/125] This adds support for the new-ish options: QUATERNION B_BONE_REST INVERT_VERTGROUP MULTIMODIFIER to the bpy armature modifier API. It also fixes a significant problem - In the docs, it refers to the 'VERTGROUP' field as being a string value, shared by lattice, armature, etc, referring to the 'VGroup' field in the armature modifier that defines a vertex group 'mask' which the armature's effect is restricted to. However, previously, for some very mistaken reason, in processing the getters/setters for the armature modifier, the VERTGROUP field was pointing to the quite different 'Vert. Groups' toggle in the armature modifier, that enables or disables using vertex groups for deformation (as opposed to envelopes). I've fixed this, so VERTGROUP points to the VGroup string, as is already defined in the docs and consistent with other modifiers like Lattice. A new field: 'VGROUPS' has been added, which is the analog to the 'Vert Groups' toggle. --- source/blender/python/api2_2x/Modifier.c | 53 +++++++++++++++++-- source/blender/python/api2_2x/doc/Modifier.py | 5 ++ 2 files changed, 53 insertions(+), 5 deletions(-) diff --git a/source/blender/python/api2_2x/Modifier.c b/source/blender/python/api2_2x/Modifier.c index 9775bce2235..3bef0eead09 100644 --- a/source/blender/python/api2_2x/Modifier.c +++ b/source/blender/python/api2_2x/Modifier.c @@ -83,7 +83,12 @@ enum mod_constants { EXPP_MOD_UV, /*ARMATURE SPECIFIC*/ + EXPP_MOD_VGROUPS, EXPP_MOD_ENVELOPES, + EXPP_MOD_QUATERNION, + EXPP_MOD_B_BONE_REST, + EXPP_MOD_INVERT_VERTGROUP, + EXPP_MOD_MULTIMODIFIER, /*ARRAY SPECIFIC*/ EXPP_MOD_OBJECT_OFFSET, @@ -376,12 +381,23 @@ static PyObject *armature_getter( BPy_Modifier * self, int type ) case EXPP_MOD_OBJECT: return Object_CreatePyObject( md->object ); case EXPP_MOD_VERTGROUP: - return PyBool_FromLong( ( long )( md->deformflag & 1 ) ) ; + return PyString_FromString( md->defgrp_name ) ; + case EXPP_MOD_VGROUPS: + return EXPP_getBitfield( &md->deformflag, ARM_DEF_VGROUP, 'h' ); case EXPP_MOD_ENVELOPES: - return PyBool_FromLong( ( long )( md->deformflag & 2 ) ) ; + return EXPP_getBitfield( &md->deformflag, ARM_DEF_ENVELOPE, 'h' ); + case EXPP_MOD_QUATERNION: + return EXPP_getBitfield( &md->deformflag, ARM_DEF_QUATERNION, 'h' ); + case EXPP_MOD_B_BONE_REST: + return EXPP_getBitfield( &md->deformflag, ARM_DEF_B_BONE_REST, 'h' ); + case EXPP_MOD_INVERT_VERTGROUP: + return EXPP_getBitfield( &md->deformflag, ARM_DEF_INVERT_VGROUP, 'h' ); + case EXPP_MOD_MULTIMODIFIER: + return EXPP_getBitfield( &md->multi, 1, 'h' ); default: return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" ); } + return 0; } static int armature_setter( BPy_Modifier *self, int type, PyObject *value ) @@ -391,13 +407,30 @@ static int armature_setter( BPy_Modifier *self, int type, PyObject *value ) switch( type ) { case EXPP_MOD_OBJECT: return GenericLib_assignData(value, (void **) &md->object, 0, 0, ID_OB, OB_ARMATURE); - case EXPP_MOD_VERTGROUP: - return EXPP_setBitfield( value, &md->deformflag, 1, 'h' ); + case EXPP_MOD_VERTGROUP: { + char *defgrp_name = PyString_AsString( value ); + if( !defgrp_name ) + return EXPP_ReturnIntError( PyExc_TypeError, + "expected string arg" ); + BLI_strncpy( md->defgrp_name, defgrp_name, sizeof( md->defgrp_name ) ); + break; + } + case EXPP_MOD_VGROUPS: + return EXPP_setBitfield( value, &md->deformflag, ARM_DEF_VGROUP, 'h' ); case EXPP_MOD_ENVELOPES: - return EXPP_setBitfield( value, &md->deformflag, 2, 'h' ); + return EXPP_setBitfield( value, &md->deformflag, ARM_DEF_ENVELOPE, 'h' ); + case EXPP_MOD_QUATERNION: + return EXPP_setBitfield( value, &md->deformflag, ARM_DEF_QUATERNION, 'h' ); + case EXPP_MOD_B_BONE_REST: + return EXPP_setBitfield( value, &md->deformflag, ARM_DEF_B_BONE_REST, 'h' ); + case EXPP_MOD_INVERT_VERTGROUP: + return EXPP_setBitfield( value, &md->deformflag, ARM_DEF_INVERT_VGROUP, 'h' ); + case EXPP_MOD_MULTIMODIFIER: + return EXPP_setBitfield( value, &md->multi, 1, 'h' ); default: return EXPP_ReturnIntError( PyExc_KeyError, "key not found" ); } + return 0; } static PyObject *lattice_getter( BPy_Modifier * self, int type ) @@ -1595,8 +1628,18 @@ for var in st.replace(',','').split('\n'): PyInt_FromLong( EXPP_MOD_OPTIMAL ) ); PyConstant_Insert( d, "UV", PyInt_FromLong( EXPP_MOD_UV ) ); + PyConstant_Insert( d, "VGROUPS", + PyInt_FromLong( EXPP_MOD_VGROUPS ) ); PyConstant_Insert( d, "ENVELOPES", PyInt_FromLong( EXPP_MOD_ENVELOPES ) ); + PyConstant_Insert( d, "QUATERNION", + PyInt_FromLong( EXPP_MOD_QUATERNION ) ); + PyConstant_Insert( d, "B_BONE_REST", + PyInt_FromLong( EXPP_MOD_B_BONE_REST ) ); + PyConstant_Insert( d, "INVERT_VERTGROUP", + PyInt_FromLong( EXPP_MOD_INVERT_VERTGROUP ) ); + PyConstant_Insert( d, "MULTIMODIFIER", + PyInt_FromLong( EXPP_MOD_MULTIMODIFIER ) ); PyConstant_Insert( d, "OBJECT_OFFSET", PyInt_FromLong( EXPP_MOD_OBJECT_OFFSET ) ); PyConstant_Insert( d, "OBJECT_CURVE", diff --git a/source/blender/python/api2_2x/doc/Modifier.py b/source/blender/python/api2_2x/doc/Modifier.py index 1d7d2e121c9..47f72e566b2 100644 --- a/source/blender/python/api2_2x/doc/Modifier.py +++ b/source/blender/python/api2_2x/doc/Modifier.py @@ -93,7 +93,12 @@ Example:: - SCALE_VEC - Used for Array only (3d Vector) - MERGE_DIST - Used for Array only (float) + - INVERT_VERTGROUP - Used for Armature only (bool) - ENVELOPES - Used for Armature only (bool) + - VGROUPS - Used for Armature only (bool) + - QUATERNION - Used for Armature only (bool) + - B_BONE_REST - Used for Armature only (bool) + - MULTIMODIFIER - Used for Armature only (bool) - START - Used for Build only (int) - SEED - Used for Build only (int) From 0a7767d597dc92727a64fae676cbf03c9ef17915 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 18 Sep 2008 01:46:28 +0000 Subject: [PATCH 122/125] Fix for bug #3858: the game engine mouse focus sensor did not work correct if there was more than one camera. It shoots rays from the active camera, but used the viewport from whichever camera was drawn last, now it uses the correct vieport. --- .../Converter/BL_BlenderDataConversion.cpp | 2 +- .../gameengine/Converter/KX_ConvertSensors.cpp | 2 ++ source/gameengine/Converter/KX_ConvertSensors.h | 1 + source/gameengine/Ketsji/KX_KetsjiEngine.cpp | 6 +++--- source/gameengine/Ketsji/KX_KetsjiEngine.h | 3 ++- .../gameengine/Ketsji/KX_MouseFocusSensor.cpp | 17 +++++++++++------ source/gameengine/Ketsji/KX_MouseFocusSensor.h | 10 ++++------ 7 files changed, 24 insertions(+), 17 deletions(-) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index c3992d02eee..425e07a257c 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -2471,7 +2471,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, struct Object* blenderobj = converter->FindBlenderObject(gameobj); int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0; bool isInActiveLayer = (blenderobj->lay & layerMask)!=0; - BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,keydev,executePriority,layerMask,isInActiveLayer,canvas,converter); + BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,keydev,executePriority,layerMask,isInActiveLayer,canvas,converter); // set the init state to all objects gameobj->SetInitState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state); } diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index f16855955ff..be0bb8103c0 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -92,6 +92,7 @@ void BL_ConvertSensors(struct Object* blenderobject, class KX_GameObject* gameobj, SCA_LogicManager* logicmgr, KX_Scene* kxscene, + KX_KetsjiEngine* kxengine, SCA_IInputDevice* keydev, int & executePriority, int activeLayerBitInfo, @@ -508,6 +509,7 @@ void BL_ConvertSensors(struct Object* blenderobject, trackfocus, canvas, kxscene, + kxengine, gameobj); } } else { diff --git a/source/gameengine/Converter/KX_ConvertSensors.h b/source/gameengine/Converter/KX_ConvertSensors.h index 73da51f47f0..b18ffc10a2a 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.h +++ b/source/gameengine/Converter/KX_ConvertSensors.h @@ -33,6 +33,7 @@ void BL_ConvertSensors(struct Object* blenderobject, class KX_GameObject* gameobj, class SCA_LogicManager* logicmgr, class KX_Scene* kxscene, + class KX_KetsjiEngine* kxengine, class SCA_IInputDevice* keydev, int & executePriority , int activeLayerBitInfo, diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 888dcf3d01f..c7b0d7b3ea3 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -299,7 +299,7 @@ void KX_KetsjiEngine::ClearFrame() list::iterator it; for(it = cameras->begin(); it != cameras->end(); it++) { - SetupViewport(scene, (*it), area, viewport); + GetSceneViewport(scene, (*it), area, viewport); if(!doclear) { clearvp = viewport; @@ -894,7 +894,7 @@ void KX_KetsjiEngine::SetCameraOverrideClipping(float near, float far) m_overrideCamFar = far; } -void KX_KetsjiEngine::SetupViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport) +void KX_KetsjiEngine::GetSceneViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport) { // In this function we make sure the rasterizer settings are upto // date. We compute the viewport so that logic @@ -1001,7 +1001,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) if (!cam) return; - SetupViewport(scene, cam, area, viewport); + GetSceneViewport(scene, cam, area, viewport); // store the computed viewport in the scene scene->SetSceneViewport(viewport); diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 8fe8731dc05..1aa067a9962 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -179,7 +179,6 @@ private: /** Blue component of framing bar color. */ float m_overrideFrameColorB; - void SetupViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport); void RenderFrame(KX_Scene* scene, KX_Camera* cam); void PostRenderFrame(); void RenderDebugProperties(); @@ -230,6 +229,8 @@ public: void SuspendScene(const STR_String& scenename); void ResumeScene(const STR_String& scenename); + void GetSceneViewport(KX_Scene* scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport); + void SetDrawType(int drawingtype); void SetCameraZoom(float camzoom); diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index 3156f543ed5..6f76448707c 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -62,12 +62,14 @@ KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr, int focusmode, RAS_ICanvas* canvas, KX_Scene* kxscene, + KX_KetsjiEngine *kxengine, SCA_IObject* gameobj, PyTypeObject* T) : SCA_MouseSensor(eventmgr, startx, starty, mousemode, gameobj, T), m_focusmode(focusmode), m_gp_canvas(canvas), - m_kxscene(kxscene) + m_kxscene(kxscene), + m_kxengine(kxengine) { Init(); } @@ -193,11 +195,14 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void) * calculations don't bomb. Maybe we should explicitly guard for * division by 0.0...*/ - /** - * Get the scenes current viewport. - */ + KX_Camera* cam = m_kxscene->GetActiveCamera(); - const RAS_Rect & viewport = m_kxscene->GetSceneViewport(); + /* get the scenes current viewport. we recompute it because there + * may be multiple cameras and m_kxscene->GetSceneViewport() only + * has the one that was last drawn */ + + RAS_Rect area, viewport; + m_kxengine->GetSceneViewport(m_kxscene, cam, area, viewport); float height = float(viewport.m_y2 - viewport.m_y1 + 1); float width = float(viewport.m_x2 - viewport.m_x1 + 1); @@ -205,9 +210,9 @@ bool KX_MouseFocusSensor::ParentObjectHasFocus(void) float x_lb = float(viewport.m_x1); float y_lb = float(viewport.m_y1); - KX_Camera* cam = m_kxscene->GetActiveCamera(); /* There's some strangeness I don't fully get here... These values * _should_ be wrong! */ + /* old: */ float nearclip = 0.0; diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h index a6cc39d66eb..6731444699b 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h @@ -56,6 +56,7 @@ class KX_MouseFocusSensor : public SCA_MouseSensor int focusmode, RAS_ICanvas* canvas, KX_Scene* kxscene, + KX_KetsjiEngine* kxengine, SCA_IObject* gameobj, PyTypeObject* T=&Type ); @@ -142,12 +143,6 @@ class KX_MouseFocusSensor : public SCA_MouseSensor MT_Vector3 m_hitNormal; - /** - * Ref to the engine, for retrieving a reference to the current - * scene. */ - class KX_KetsjiEngine* m_engine; - - /** * The active canvas. The size of this canvas determines a part of * the start position of the picking ray. */ @@ -158,6 +153,9 @@ class KX_MouseFocusSensor : public SCA_MouseSensor * determines a part of the start location of the picking ray. */ KX_Scene* m_kxscene; + /** + * The KX engine is needed for computing the viewport */ + KX_KetsjiEngine* m_kxengine; }; #endif //__KX_MOUSESENSOR From beb7738a299579e771295e013961ef3af139d1e5 Mon Sep 17 00:00:00 2001 From: Daniel Genrich Date: Thu, 18 Sep 2008 01:55:43 +0000 Subject: [PATCH 123/125] Hopefully fixes crash in particle system with effector enabled --- source/blender/blenkernel/BKE_particle.h | 1 + .../blenkernel/intern/particle_system.c | 26 ++++++++++++------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index ea1dc7407db..a1a9a883c4f 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -73,6 +73,7 @@ typedef struct ParticleEffectorCache { short type, psys_nbr; struct Object obcopy; /* for restoring transformation data */ + struct RNG *rng; /* random noise generator for e.g. wind */ } ParticleEffectorCache; typedef struct ParticleReactEvent { diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 3a93c0dab02..a0c4bd91da4 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2317,12 +2317,6 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy else if(pd->forcefield) { type |= PSYS_EC_EFFECTOR; - - if(pd->forcefield == PFIELD_WIND) - { - pd->rng = rng_new(1); - rng_srandom(pd->rng, (unsigned int)(ceil(PIL_check_seconds_timer()))); // use better seed - } } } @@ -2335,6 +2329,9 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy ec->type=type; ec->distances=0; ec->locations=0; + ec->rng = rng_new(1); + rng_srandom(ec->rng, (unsigned int)(ceil(PIL_check_seconds_timer()))); // use better seed + BLI_addtail(lb, ec); } @@ -2353,7 +2350,9 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy if((epsys->part->pd && epsys->part->pd->forcefield) || (epsys->part->pd2 && epsys->part->pd2->forcefield)) + { type=PSYS_EC_PARTICLE; + } if(epart->type==PART_REACTOR) { tob=epsys->target_ob; @@ -2368,6 +2367,9 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy ec->ob= ob; ec->type=type; ec->psys_nbr=i; + ec->rng = rng_new(1); + rng_srandom(ec->rng, (unsigned int)(ceil(PIL_check_seconds_timer()))); + BLI_addtail(lb, ec); } } @@ -2417,6 +2419,9 @@ void psys_init_effectors(Object *obsrc, Group *group, ParticleSystem *psys) void psys_end_effectors(ParticleSystem *psys) { + /* NOTE: + ec->ob is not valid in here anymore! - dg + */ ListBase *lb=&psys->effectors; if(lb->first) { ParticleEffectorCache *ec; @@ -2436,8 +2441,9 @@ void psys_end_effectors(ParticleSystem *psys) if(ec->tree) BLI_kdtree_free(ec->tree); - if(ec->ob->pd && (ec->ob->pd->forcefield == PFIELD_WIND)) - rng_free(ec->ob->pd->rng); + if(ec->rng) + rng_free(ec->rng); + } BLI_freelistN(lb); @@ -2572,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,pd->rng,pd->f_noise,charge,pa->size); + pa->state.vel,force_field,pd->flag&PFIELD_PLANAR,ec->rng,pd->f_noise,charge,pa->size); } } if(ec->type & PSYS_EC_PARTICLE){ @@ -2616,7 +2622,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,epart->size,pd->f_damp,estate.vel,vec_to_part, - state->vel,force_field,0, pd->rng, pd->f_noise,charge,pa->size); + state->vel,force_field,0, ec->rng, pd->f_noise,charge,pa->size); } } else if(pd && pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){ From 8d1163c639253e76fec3f69fead716a51068ea37 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 18 Sep 2008 03:05:02 +0000 Subject: [PATCH 124/125] scons options BF_CXX, WITH_BF_STATICCXX, BF_CXX_LIB_STATIC for static linking to stdc++ because of problems running blender on some systems. --- SConstruct | 7 +++++++ config/darwin-config.py | 5 +++++ config/linux2-config.py | 4 ++++ config/linuxcross-config.py | 5 +++++ config/sunos5-config.py | 5 +++++ config/win32-vc-config.py | 5 +++++ tools/Blender.py | 3 ++- tools/btools.py | 8 ++++++-- 8 files changed, 39 insertions(+), 3 deletions(-) diff --git a/SConstruct b/SConstruct index 92547bf6756..356f116e290 100644 --- a/SConstruct +++ b/SConstruct @@ -241,6 +241,13 @@ if len(B.quickdebug) > 0 and printdebug != 0: for l in B.quickdebug: print "\t" + l +# remove stdc++ from LLIBS if we are building a statc linked CXXFLAGS +if env['WITH_BF_STATICCXX']: + if 'stdc++' in env['LLIBS']: + env['LLIBS'] = env['LLIBS'].replace('stdc++', ' ') + else: + print '\tcould not remove stdc++ library from LLIBS, WITH_BF_STATICCXX may not work for your platform' + # check target for blenderplayer. Set WITH_BF_PLAYER if found on cmdline if 'blenderplayer' in B.targets: env['WITH_BF_PLAYER'] = True diff --git a/config/darwin-config.py b/config/darwin-config.py index 70d2281b1f7..0eb275dcaf4 100644 --- a/config/darwin-config.py +++ b/config/darwin-config.py @@ -95,6 +95,11 @@ BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' # Warning, this static lib configuration is untested! users of this OS please confirm. BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_CXX = '/usr' +WITH_BF_STATICCXX = 'false' +BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a' + WITH_BF_SDL = 'true' BF_SDL = LIBDIR + '/sdl' #$(shell sdl-config --prefix) BF_SDL_INC = '${BF_SDL}/include' #$(shell $(BF_SDL)/bin/sdl-config --cflags) diff --git a/config/linux2-config.py b/config/linux2-config.py index f2df9b86c6b..cd7e6659af1 100644 --- a/config/linux2-config.py +++ b/config/linux2-config.py @@ -25,6 +25,10 @@ BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' # BF_OPENAL_LIB = 'openal alut' # BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a ${BF_OPENAL}/lib/libalut.a' +BF_CXX = '/usr' +WITH_BF_STATICCXX = 'false' +BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a' + WITH_BF_SDL = 'true' BF_SDL = '/usr' #$(shell sdl-config --prefix) BF_SDL_INC = '${BF_SDL}/include/SDL' #$(shell $(BF_SDL)/bin/sdl-config --cflags) diff --git a/config/linuxcross-config.py b/config/linuxcross-config.py index 3172a4a060c..9d58512151b 100644 --- a/config/linuxcross-config.py +++ b/config/linuxcross-config.py @@ -22,6 +22,11 @@ BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' # Warning, this static lib configuration is untested! users of this OS please confirm. BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_CXX = '/usr' +WITH_BF_STATICCXX = 'false' +BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a' + WITH_BF_SDL = 'true' BF_SDL = LIBDIR + '/sdl' BF_SDL_INC = '${BF_SDL}/include' diff --git a/config/sunos5-config.py b/config/sunos5-config.py index 84e2f57bd3e..bfb1513ca3f 100644 --- a/config/sunos5-config.py +++ b/config/sunos5-config.py @@ -17,6 +17,11 @@ BF_OPENAL_LIB = 'openal' # Warning, this static lib configuration is untested! users of this OS please confirm. BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' +# Warning, this static lib configuration is untested! users of this OS please confirm. +BF_CXX = '/usr' +WITH_BF_STATICCXX = 'false' +BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a' + WITH_BF_SDL = 'true' BF_SDL = '/usr/local' #$(shell sdl-config --prefix) BF_SDL_INC = '${BF_SDL}/include/SDL' #$(shell $(BF_SDL)/bin/sdl-config --cflags) diff --git a/config/win32-vc-config.py b/config/win32-vc-config.py index 725cd7133da..063d1461def 100644 --- a/config/win32-vc-config.py +++ b/config/win32-vc-config.py @@ -27,6 +27,11 @@ BF_OPENAL_LIBPATH = '${BF_OPENAL}/lib' # Warning, this static lib configuration is untested! users of this OS please confirm. BF_OPENAL_LIB_STATIC = '${BF_OPENAL}/lib/libopenal.a' +# TODO - are these useful on win32? +# BF_CXX = '/usr' +# WITH_BF_STATICCXX = 'false' +# BF_CXX_LIB_STATIC = '${BF_CXX}/lib/libstdc++.a' + WITH_BF_ICONV = 'true' BF_ICONV = LIBDIR + '/iconv' BF_ICONV_INC = '${BF_ICONV}/include' diff --git a/tools/Blender.py b/tools/Blender.py index b5f32f24551..2a63ca5b697 100644 --- a/tools/Blender.py +++ b/tools/Blender.py @@ -120,7 +120,8 @@ def setup_staticlibs(lenv): libincs += Split(lenv['BF_FFMPEG_LIBPATH']) - + if lenv['WITH_BF_STATICCXX']: + statlibs += Split(lenv['BF_CXX_LIB_STATIC']) if lenv['WITH_BF_OPENEXR']: libincs += Split(lenv['BF_OPENEXR_LIBPATH']) if lenv['WITH_BF_STATICOPENEXR']: diff --git a/tools/btools.py b/tools/btools.py index be23b1d7024..ffefef06a5a 100755 --- a/tools/btools.py +++ b/tools/btools.py @@ -55,8 +55,9 @@ def validate_arguments(args, bc): 'CFLAGS', 'CCFLAGS', 'CPPFLAGS', 'REL_CFLAGS', 'REL_CCFLAGS', 'C_WARN', 'CC_WARN', 'LLIBS', 'PLATFORM_LINKFLAGS', - 'BF_PROFILE_FLAGS', 'LCGDIR', 'WITH_BF_VERSE', - 'BF_VERSE_INCLUDE', + 'BF_PROFILE_FLAGS', 'LCGDIR', + 'BF_CXX', 'WITH_BF_STATICCXX', 'BF_CXX_LIB_STATIC' + 'WITH_BF_VERSE', 'BF_VERSE_INCLUDE', 'VERSE_BUILD_BINARY', 'VERSE_BUILD_DIR', 'VERSE_REGEN_PROTO', 'BF_TWEAK_MODE', 'BF_SPLIT_SRC', 'WITHOUT_BF_INSTALL', @@ -256,6 +257,9 @@ def read_opts(cfg, args): ('BF_SOLID_INC', 'Solid include path', ''), ('BF_WINTAB', 'WinTab base dir', ''), ('BF_WINTAB_INC', 'WinTab include dir', ''), + ('BF_CXX', 'c++ base path for libstdc++, only used when static linking', ''), + ('WITH_BF_STATICCXX', 'static link to stdc++', 'false'), + ('BF_CXX_LIB_STATIC', 'static library path for stdc++', ''), ## ##WITH_BF_NSPR = 'true' ##BF_NSPR = $(LCGDIR)/nspr From 423b05390434c310c0f0e59ef62fce79287c581b Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Thu, 18 Sep 2008 11:49:57 +0000 Subject: [PATCH 125/125] Grease Pencil - Stroke Sensitivity: Sensitivity to mouse movement when drawing can now be customised in the User Prefs, under 'Edit Methods'. --- source/blender/makesdna/DNA_userdef_types.h | 3 ++- source/blender/src/gpencil.c | 7 ++++--- source/blender/src/space.c | 13 +++++++++++++ source/blender/src/usiblender.c | 10 ++++++++-- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 2474161da07..5d36d5ca973 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -188,7 +188,8 @@ typedef struct UserDef { char fontname[256]; // FILE_MAXDIR+FILE length struct ListBase themes; short undosteps; - short undomemory, pad[3]; + short undomemory; + short gp_manhattendist, gp_euclideandist, pad; short curssize; short tb_leftmouse, tb_rightmouse; struct SolidLight light[3]; diff --git a/source/blender/src/gpencil.c b/source/blender/src/gpencil.c index c7540bc4a1f..e51636b6748 100644 --- a/source/blender/src/gpencil.c +++ b/source/blender/src/gpencil.c @@ -992,11 +992,12 @@ void gpencil_convert_menu (void) #define GP_STROKE_BUFFER_MAX 5000 /* Hardcoded sensitivity thresholds... */ -// TODO: one day, these might be added to the UI if it is necessary /* minimum number of pixels mouse should move before new point created */ -#define MIN_MANHATTEN_PX 3 +//#define MIN_MANHATTEN_PX 3 +#define MIN_MANHATTEN_PX U.gp_manhattendist /* minimum length of new segment before new point can be added */ -#define MIN_EUCLIDEAN_PX 20 +//#define MIN_EUCLIDEAN_PX 20 +#define MIN_EUCLIDEAN_PX U.gp_euclideandist /* ------ */ diff --git a/source/blender/src/space.c b/source/blender/src/space.c index 140ec59e360..fb86620201b 100644 --- a/source/blender/src/space.c +++ b/source/blender/src/space.c @@ -4055,6 +4055,19 @@ void drawinfospace(ScrArea *sa, void *spacedata) (xpos+edgsp+(8*midsp)+(3*mpref)+(5*spref)),y1,(spref+edgsp),buth, &(U.dupflag), 0, 0, 0, 0, "Causes ipo data to be duplicated with Shift+D"); uiBlockEndAlign(block); + + uiDefBut(block, LABEL,0,"Grease Pencil:", + (xpos+(2*edgsp)+(3*midsp)+(3*mpref)+spref),y6label,mpref,buth, + 0, 0, 0, 0, 0, ""); + + uiBlockBeginAlign(block); + uiDefButS(block, NUM, 0, "Manhatten Dist:", + (xpos+(4*midsp)+(3*mpref)+mpref),y5,mpref,buth, + &(U.gp_manhattendist), 0, 100, 0, 0, "Pixels moved by mouse per axis when drawing stroke"); + uiDefButS(block, NUM, 0, "Euclidean Dist:", + (xpos+(5*midsp)+(3*mpref)+(2*mpref)),y5,mpref,buth, + &(U.gp_euclideandist), 0, 100, 0, 0, "Distance moved by mouse when drawing stroke (in pixels) to include"); + uiBlockEndAlign(block); } else if(U.userpref == 2) { /* language & colors */ diff --git a/source/blender/src/usiblender.c b/source/blender/src/usiblender.c index aa49065320b..88cdc558f2b 100644 --- a/source/blender/src/usiblender.c +++ b/source/blender/src/usiblender.c @@ -480,9 +480,11 @@ static void init_userdef_file(void) if ((G.main->versionfile < 245) || (G.main->versionfile == 245 && G.main->subversionfile < 16)) { U.flag |= USER_ADD_VIEWALIGNED|USER_ADD_EDITMODE; } - if ((G.main->versionfile < 247) || (G.main->versionfile == 247 && G.main->subversionfile < 1)) { + if ((G.main->versionfile < 247) || (G.main->versionfile == 247 && G.main->subversionfile <= 2)) { bTheme *btheme; - for(btheme= U.themes.first; btheme; btheme= btheme->next) { + + /* adjust themes */ + for (btheme= U.themes.first; btheme; btheme= btheme->next) { char *col; /* IPO Editor: Handles/Vertices */ @@ -499,6 +501,10 @@ static void init_userdef_file(void) col = btheme->tv3d.vertex_select; SETCOL(btheme->tseq.vertex_select, col[0], col[1], col[2], 255); } + + /* define grease-pencil distances */ + U.gp_manhattendist= 3; + U.gp_euclideandist= 20; } /* GL Texture Garbage Collection (variable abused above!) */