Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/softbody.c
| Show First 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | |||||
| /* types */ | /* types */ | ||||
| #include "DNA_object_types.h" | #include "DNA_object_types.h" | ||||
| #include "DNA_scene_types.h" | #include "DNA_scene_types.h" | ||||
| #include "DNA_lattice_types.h" | #include "DNA_lattice_types.h" | ||||
| #include "DNA_curve_types.h" | #include "DNA_curve_types.h" | ||||
| #include "DNA_mesh_types.h" | #include "DNA_mesh_types.h" | ||||
| #include "DNA_meshdata_types.h" | #include "DNA_meshdata_types.h" | ||||
| #include "DNA_group_types.h" | |||||
| #include "BLI_math.h" | #include "BLI_math.h" | ||||
| #include "BLI_utildefines.h" | #include "BLI_utildefines.h" | ||||
| #include "BLI_listbase.h" | #include "BLI_listbase.h" | ||||
| #include "BLI_ghash.h" | #include "BLI_ghash.h" | ||||
| #include "BLI_threads.h" | #include "BLI_threads.h" | ||||
| #include "BKE_curve.h" | #include "BKE_curve.h" | ||||
| ▲ Show 20 Lines • Show All 417 Lines • ▼ Show 20 Lines | if (ccdm && (ccdm->savety == CCD_SAVETY )) { /*make sure we're not nuking objects we don't know*/ | ||||
| MEM_freeN((void *)ccdm->tri); | MEM_freeN((void *)ccdm->tri); | ||||
| if (ccdm->mprevvert) MEM_freeN((void *)ccdm->mprevvert); | if (ccdm->mprevvert) MEM_freeN((void *)ccdm->mprevvert); | ||||
| MEM_freeN(ccdm->mima); | MEM_freeN(ccdm->mima); | ||||
| MEM_freeN(ccdm); | MEM_freeN(ccdm); | ||||
| ccdm = NULL; | ccdm = NULL; | ||||
| } | } | ||||
| } | } | ||||
| static void ccd_build_deflector_hash(Scene *scene, Object *vertexowner, GHash *hash) | static void ccd_build_deflector_hash(Scene *scene, Object *vertexowner, Group *group, GHash *hash) | ||||
| { | { | ||||
| Base *base= scene->base.first; | Base *base= scene->base.first; | ||||
| Object *ob; | Object *ob; | ||||
| if (!hash) return; | if (!hash) return; | ||||
| if (group) { | |||||
lukastoenne: In terms of code style, would prefer two distinct functions, since it's either group-based… | |||||
| /* Explicit collision group */ | |||||
| GroupObject *go; | |||||
| for (go = group->gobject.first; go; go = go->next) { | |||||
| ob = go->ob; | |||||
| if (ob == vertexowner || ob->type != OB_MESH) | |||||
| continue; | |||||
| /* only with deflecting set */ | |||||
| if (ob->pd && ob->pd->deflect && BLI_ghash_lookup(hash, ob) == NULL) { | |||||
| ccd_Mesh *ccdmesh = ccd_mesh_make(ob); | |||||
| BLI_ghash_insert(hash, ob, ccdmesh); | |||||
| } | |||||
| } | |||||
| return; | |||||
| } | |||||
| while (base) { | while (base) { | ||||
| /*Only proceed for mesh object in same layer */ | /*Only proceed for mesh object in same layer */ | ||||
| if (base->object->type==OB_MESH && (base->lay & vertexowner->lay)) { | if (base->object->type==OB_MESH && (base->lay & vertexowner->lay)) { | ||||
| ob= base->object; | ob= base->object; | ||||
| if ((vertexowner) && (ob == vertexowner)) { | if ((vertexowner) && (ob == vertexowner)) { | ||||
| /* if vertexowner is given we don't want to check collision with owner object */ | /* if vertexowner is given we don't want to check collision with owner object */ | ||||
| base = base->next; | base = base->next; | ||||
| continue; | continue; | ||||
| } | } | ||||
| /*+++ only with deflecting set */ | /*+++ only with deflecting set */ | ||||
| if (ob->pd && ob->pd->deflect && BLI_ghash_lookup(hash, ob) == NULL) { | if (ob->pd && ob->pd->deflect && BLI_ghash_lookup(hash, ob) == NULL) { | ||||
| ccd_Mesh *ccdmesh = ccd_mesh_make(ob); | ccd_Mesh *ccdmesh = ccd_mesh_make(ob); | ||||
| BLI_ghash_insert(hash, ob, ccdmesh); | BLI_ghash_insert(hash, ob, ccdmesh); | ||||
| }/*--- only with deflecting set */ | }/*--- only with deflecting set */ | ||||
| }/* mesh && layer*/ | }/* mesh && layer*/ | ||||
| base = base->next; | base = base->next; | ||||
| } /* while (base) */ | } /* while (base) */ | ||||
| } | } | ||||
| static void ccd_update_deflector_hash(Scene *scene, Object *vertexowner, GHash *hash) | static void ccd_update_deflector_hash(Scene *scene, Object *vertexowner, Group *group, GHash *hash) | ||||
| { | { | ||||
| Base *base= scene->base.first; | Base *base= scene->base.first; | ||||
| Object *ob; | Object *ob; | ||||
| if ((!hash) || (!vertexowner)) return; | if ((!hash) || (!vertexowner)) return; | ||||
| if (group) { | |||||
| /* Explicit collision group */ | |||||
| GroupObject *go; | |||||
| for (go = group->gobject.first; go; go = go->next) { | |||||
| ob = go->ob; | |||||
| if (ob == vertexowner || ob->type != OB_MESH) | |||||
| continue; | |||||
| /* only with deflecting set */ | |||||
| if (ob->pd && ob->pd->deflect) { | |||||
| ccd_Mesh *ccdmesh = BLI_ghash_lookup(hash, ob); | |||||
| if (ccdmesh) | |||||
| ccd_mesh_update(ob, ccdmesh); | |||||
| } | |||||
| } | |||||
| return; | |||||
| } | |||||
| while (base) { | while (base) { | ||||
| /*Only proceed for mesh object in same layer */ | /*Only proceed for mesh object in same layer */ | ||||
| if (base->object->type==OB_MESH && (base->lay & vertexowner->lay)) { | if (base->object->type==OB_MESH && (base->lay & vertexowner->lay)) { | ||||
| ob= base->object; | ob= base->object; | ||||
| if (ob == vertexowner) { | if (ob == vertexowner) { | ||||
| /* if vertexowner is given we don't want to check collision with owner object */ | /* if vertexowner is given we don't want to check collision with owner object */ | ||||
| base = base->next; | base = base->next; | ||||
| continue; | continue; | ||||
| ▲ Show 20 Lines • Show All 389 Lines • ▼ Show 20 Lines | |||||
| ** and need to tell their neighbors exactly what happens via spring forces | ** and need to tell their neighbors exactly what happens via spring forces | ||||
| ** unless sbObjectStep( .. ) is called on sub frame timing level | ** unless sbObjectStep( .. ) is called on sub frame timing level | ||||
| ** BTW that also questions the use of a 'implicit' solvers on softbodies | ** BTW that also questions the use of a 'implicit' solvers on softbodies | ||||
| ** since that would only valid for 'slow' moving collision targets and dito particles | ** since that would only valid for 'slow' moving collision targets and dito particles | ||||
| */ | */ | ||||
| /* +++ dependency information functions*/ | /* +++ dependency information functions*/ | ||||
| static int are_there_deflectors(Scene *scene, unsigned int layer) | static int are_there_deflectors(Scene *scene, unsigned int layer, Group *group) | ||||
| { | { | ||||
| if (group) { | |||||
| GroupObject *go; | |||||
| for (go = group->gobject.first; go; go = go->next) { | |||||
| if (go->ob->pd && go->ob->pd->deflect) | |||||
| return 1; | |||||
| } | |||||
| } | |||||
| else { | |||||
| Base *base; | Base *base; | ||||
| for (base = scene->base.first; base; base= base->next) { | for (base = scene->base.first; base; base= base->next) { | ||||
| if ( (base->lay & layer) && base->object->pd) { | if ( (base->lay & layer) && base->object->pd) { | ||||
| if (base->object->pd->deflect) | if (base->object->pd->deflect) | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| static int query_external_colliders(Scene *scene, Object *me) | static int query_external_colliders(Scene *scene, Object *me, Group *group) | ||||
| { | { | ||||
| return(are_there_deflectors(scene, me->lay)); | return(are_there_deflectors(scene, me->lay, group)); | ||||
| } | } | ||||
| /* --- dependency information functions*/ | /* --- dependency information functions*/ | ||||
| /* +++ the aabb "force" section*/ | /* +++ the aabb "force" section*/ | ||||
| static int sb_detect_aabb_collisionCached(float UNUSED(force[3]), unsigned int UNUSED(par_layer), struct Object *vertexowner, float UNUSED(time)) | static int sb_detect_aabb_collisionCached(float UNUSED(force[3]), unsigned int UNUSED(par_layer), struct Object *vertexowner, float UNUSED(time)) | ||||
| { | { | ||||
| Object *ob; | Object *ob; | ||||
| ▲ Show 20 Lines • Show All 1,231 Lines • ▼ Show 20 Lines | */ | ||||
| /* float gravity; */ /* UNUSED */ | /* float gravity; */ /* UNUSED */ | ||||
| /* float iks; */ | /* float iks; */ | ||||
| float fieldfactor = -1.0f, windfactor = 0.25; | float fieldfactor = -1.0f, windfactor = 0.25; | ||||
| int do_deflector /*, do_selfcollision*/, do_springcollision, do_aero; | int do_deflector /*, do_selfcollision*/, do_springcollision, do_aero; | ||||
| /* gravity = sb->grav * sb_grav_force_scale(ob); */ /* UNUSED */ | /* gravity = sb->grav * sb_grav_force_scale(ob); */ /* UNUSED */ | ||||
| /* check conditions for various options */ | /* check conditions for various options */ | ||||
| do_deflector= query_external_colliders(scene, ob); | do_deflector= query_external_colliders(scene, ob, sb->collision_group); | ||||
| /* do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); */ /* UNUSED */ | /* do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); */ /* UNUSED */ | ||||
| do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL); | do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL); | ||||
| do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES)); | do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES)); | ||||
| /* iks = 1.0f/(1.0f-sb->inspring)-1.0f; */ /* inner spring constants function */ /* UNUSED */ | /* iks = 1.0f/(1.0f-sb->inspring)-1.0f; */ /* inner spring constants function */ /* UNUSED */ | ||||
| /* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */ | /* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */ | ||||
| if (do_springcollision || do_aero) | if (do_springcollision || do_aero) | ||||
| ▲ Show 20 Lines • Show All 47 Lines • ▼ Show 20 Lines | else { | ||||
| int do_deflector, do_selfcollision, do_springcollision, do_aero; | int do_deflector, do_selfcollision, do_springcollision, do_aero; | ||||
| if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { | if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { | ||||
| copy_v3_v3(gravity, scene->physics_settings.gravity); | copy_v3_v3(gravity, scene->physics_settings.gravity); | ||||
| mul_v3_fl(gravity, sb_grav_force_scale(ob)*sb->effector_weights->global_gravity); | mul_v3_fl(gravity, sb_grav_force_scale(ob)*sb->effector_weights->global_gravity); | ||||
| } | } | ||||
| /* check conditions for various options */ | /* check conditions for various options */ | ||||
| do_deflector= query_external_colliders(scene, ob); | do_deflector= query_external_colliders(scene, ob, sb->collision_group); | ||||
| do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); | do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); | ||||
| do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL); | do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL); | ||||
| do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES)); | do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES)); | ||||
| iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */ | iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */ | ||||
| /* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */ | /* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */ | ||||
| if (do_springcollision || do_aero) scan_for_ext_spring_forces(scene, ob, timenow); | if (do_springcollision || do_aero) scan_for_ext_spring_forces(scene, ob, timenow); | ||||
| ▲ Show 20 Lines • Show All 1,194 Lines • ▼ Show 20 Lines | static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime) | ||||
| sst=PIL_check_seconds_timer(); | sst=PIL_check_seconds_timer(); | ||||
| /* Integration back in time is possible in theory, but pretty useless here. | /* Integration back in time is possible in theory, but pretty useless here. | ||||
| * So we refuse to do so. Since we do not know anything about 'outside' changes | * So we refuse to do so. Since we do not know anything about 'outside' changes | ||||
| * especially colliders we refuse to go more than 10 frames. | * especially colliders we refuse to go more than 10 frames. | ||||
| */ | */ | ||||
| if (dtime < 0 || dtime > 10.5f) return; | if (dtime < 0 || dtime > 10.5f) return; | ||||
| ccd_update_deflector_hash(scene, ob, sb->scratch->colliderhash); | ccd_update_deflector_hash(scene, ob, sb->collision_group, sb->scratch->colliderhash); | ||||
| if (sb->scratch->needstobuildcollider) { | if (sb->scratch->needstobuildcollider) { | ||||
| if (query_external_colliders(scene, ob)) { | if (query_external_colliders(scene, ob, sb->collision_group)) { | ||||
| ccd_build_deflector_hash(scene, ob, sb->scratch->colliderhash); | ccd_build_deflector_hash(scene, ob, sb->collision_group, sb->scratch->colliderhash); | ||||
| } | } | ||||
| sb->scratch->needstobuildcollider=0; | sb->scratch->needstobuildcollider=0; | ||||
| } | } | ||||
| if (sb->solver_ID < 2) { | if (sb->solver_ID < 2) { | ||||
| /* special case of 2nd order Runge-Kutta type AKA Heun */ | /* special case of 2nd order Runge-Kutta type AKA Heun */ | ||||
| int mid_flags=0; | int mid_flags=0; | ||||
| float err = 0; | float err = 0; | ||||
| ▲ Show 20 Lines • Show All 230 Lines • Show Last 20 Lines | |||||
In terms of code style, would prefer two distinct functions, since it's either group-based collision or layer-based, but not both. Having a return in the middle of a function after lots of code can be misleading.
But not mandatory, depends on surrounding code style here ...