diff options
author | Janne Karhu <jhkarh@gmail.com> | 2009-04-10 23:40:21 +0400 |
---|---|---|
committer | Janne Karhu <jhkarh@gmail.com> | 2009-04-10 23:40:21 +0400 |
commit | c1cf50be7947cf46c7675cd867b7121b56eae0e3 (patch) | |
tree | 1ba7b06cdea18813c4a3b161773b9b354312ef4e | |
parent | 2fff90bbb4a922f454c15dbf2d6215bd4d8c519c (diff) |
Mesh effector surface option:
- Most mesh particle effectors can now have their effection point taken per particle as the nearest point on the mesh surface.
- This is activated with the "surface" button in the effector field panel.
- Activating the option adds a "surface" entry to the modifier stack where the state of the mesh is read from.
For an example of usage see http://www.youtube.com/watch?v=3XkO1EAmJks.
-rw-r--r-- | source/blender/blenkernel/intern/modifier.c | 84 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle_system.c | 33 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 6 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_modifier_types.h | 9 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_object_force.h | 1 | ||||
-rw-r--r-- | source/blender/src/buttons_editing.c | 12 | ||||
-rw-r--r-- | source/blender/src/buttons_object.c | 43 |
7 files changed, 178 insertions, 10 deletions
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index d182e3124fc..1068950d0d6 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -6016,6 +6016,82 @@ static void collisionModifier_deformVerts( } + +/* Surface */ + +static void surfaceModifier_initData(ModifierData *md) +{ + SurfaceModifierData *surmd = (SurfaceModifierData*) md; + + surmd->bvhtree = NULL; +} + +static void surfaceModifier_freeData(ModifierData *md) +{ + SurfaceModifierData *surmd = (SurfaceModifierData*) md; + + if (surmd) + { + if(surmd->bvhtree) { + free_bvhtree_from_mesh(surmd->bvhtree); + MEM_freeN(surmd->bvhtree); + } + + surmd->dm->release(surmd->dm); + + surmd->bvhtree = NULL; + surmd->dm = NULL; + } +} + +static int surfaceModifier_dependsOnTime(ModifierData *md) +{ + return 1; +} + +static void surfaceModifier_deformVerts( + ModifierData *md, Object *ob, DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts) +{ + SurfaceModifierData *surmd = (SurfaceModifierData*) md; + DerivedMesh *dm = NULL; + float current_time = 0; + unsigned int numverts = 0, i = 0; + + if(surmd->dm) + surmd->dm->release(surmd->dm); + + /* if possible use/create DerivedMesh */ + if(derivedData) surmd->dm = CDDM_copy(derivedData); + else if(ob->type==OB_MESH) surmd->dm = CDDM_from_mesh(ob->data, ob); + + if(!ob->pd) + { + printf("surfaceModifier_deformVerts: Should not happen!\n"); + return; + } + + if(surmd->dm) + { + CDDM_apply_vert_coords(surmd->dm, vertexCos); + CDDM_calc_normals(surmd->dm); + + numverts = surmd->dm->getNumVerts ( surmd->dm ); + + /* convert to global coordinates */ + for(i = 0; i<numverts; i++) + Mat4MulVecfl(ob->obmat, CDDM_get_vert(surmd->dm, i)->co); + + if(surmd->bvhtree) + free_bvhtree_from_mesh(surmd->bvhtree); + else + surmd->bvhtree = MEM_callocN(sizeof(BVHTreeFromMesh), "BVHTreeFromMesh"); + + bvhtree_from_mesh_faces(surmd->bvhtree, surmd->dm, 0.0, 2, 6); + } +} + + /* Boolean */ static void booleanModifier_copyData(ModifierData *md, ModifierData *target) @@ -8217,6 +8293,14 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type) mti->deformVerts = collisionModifier_deformVerts; // mti->copyData = collisionModifier_copyData; + mti = INIT_TYPE(Surface); + mti->type = eModifierTypeType_OnlyDeform; + mti->initData = surfaceModifier_initData; + mti->flags = eModifierTypeFlag_AcceptsMesh; + mti->dependsOnTime = surfaceModifier_dependsOnTime; + mti->freeData = surfaceModifier_freeData; + mti->deformVerts = surfaceModifier_deformVerts; + mti = INIT_TYPE(Boolean); mti->type = eModifierTypeType_Nonconstructive; mti->flags = eModifierTypeFlag_AcceptsMesh diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 0ffdd11c37a..bbf62d033bf 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -77,6 +77,7 @@ #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_scene.h" +#include "BKE_bvhutils.h" #include "PIL_time.h" @@ -2447,7 +2448,6 @@ void psys_end_effectors(ParticleSystem *psys) if(ec->rng) rng_free(ec->rng); - } BLI_freelistN(lb); @@ -2544,6 +2544,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P ParticleData *epa; ParticleKey estate; PartDeflect *pd; + SurfaceModifierData *surmd = NULL; ListBase *lb=&psys->effectors; ParticleEffectorCache *ec; float distance, vec_to_part[3]; @@ -2571,8 +2572,34 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P if(psys->part->type!=PART_HAIR && psys->part->integrator) where_is_object_time(eob,cfra); - /* use center of object for distance calculus */ - VecSubf(vec_to_part, state->co, eob->obmat[3]); + if(pd && pd->flag&PFIELD_SURFACE) { + surmd = (SurfaceModifierData *)modifiers_findByType ( eob, eModifierType_Surface ); + } + if(surmd) { + /* closest point in the object surface is an effector */ + BVHTreeNearest nearest; + float velocity[3]; + + nearest.index = -1; + nearest.dist = FLT_MAX; + + /* using velocity corrected location allows for easier sliding over effector surface */ + VecCopyf(velocity, state->vel); + VecMulf(velocity, psys_get_timestep(psys->part)); + VecAddf(vec_to_part, state->co, velocity); + + BLI_bvhtree_find_nearest(surmd->bvhtree->tree, vec_to_part, &nearest, surmd->bvhtree->nearest_callback, surmd->bvhtree); + + if(nearest.index != -1) { + VecSubf(vec_to_part, state->co, nearest.co); + } + else + vec_to_part[0] = vec_to_part[1] = vec_to_part[2] = 0.0f; + } + else + /* use center of object for distance calculus */ + VecSubf(vec_to_part, state->co, eob->obmat[3]); + distance = VecLength(vec_to_part); falloff=effector_falloff(pd,eob->obmat[2],vec_to_part); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 06c8370bde2..63dd1e8e6cb 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3207,6 +3207,12 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb) collmd->mfaces = NULL; } + else if (md->type==eModifierType_Surface) { + SurfaceModifierData *surmd = (SurfaceModifierData*) md; + + surmd->dm = NULL; + surmd->bvhtree = NULL; + } else if (md->type==eModifierType_Hook) { HookModifierData *hmd = (HookModifierData*) md; diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index ae07434a37f..077481dfa6e 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -39,6 +39,7 @@ typedef enum ModifierType { eModifierType_Fluidsim, eModifierType_Mask, eModifierType_SimpleDeform, + eModifierType_Surface, NUM_MODIFIER_TYPES } ModifierType; @@ -418,6 +419,14 @@ typedef struct CollisionModifierData { struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */ } CollisionModifierData; +typedef struct SurfaceModifierData { + ModifierData modifier; + + struct DerivedMesh *dm; + + struct BVHTreeFromMesh *bvhtree; /* bounding volume hierarchy of the mesh faces */ +} SurfaceModifierData; + typedef enum { eBooleanModifierOp_Intersect, eBooleanModifierOp_Union, diff --git a/source/blender/makesdna/DNA_object_force.h b/source/blender/makesdna/DNA_object_force.h index 21c5242a703..49435000820 100644 --- a/source/blender/makesdna/DNA_object_force.h +++ b/source/blender/makesdna/DNA_object_force.h @@ -225,6 +225,7 @@ typedef struct SoftBody { #define PFIELD_USEMAXR 512 #define PFIELD_USEMINR 1024 #define PFIELD_TEX_ROOTCO 2048 +#define PFIELD_SURFACE 4096 /* pd->falloff */ #define PFIELD_FALL_SPHERE 0 diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 8b249815b6f..2ec30bfa864 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -1031,7 +1031,7 @@ static uiBlock *modifiers_add_menu(void *ob_v) /* Only allow adding through appropriate other interfaces */ if(ELEM3(i, eModifierType_Softbody, eModifierType_Hook, eModifierType_ParticleSystem)) continue; - if(ELEM3(i, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim)) continue; + if(ELEM4(i, eModifierType_Cloth, eModifierType_Collision, eModifierType_Surface, eModifierType_Fluidsim)) continue; if((mti->flags&eModifierTypeFlag_AcceptsCVs) || (ob->type==OB_MESH && (mti->flags&eModifierTypeFlag_AcceptsMesh))) { @@ -1771,7 +1771,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco uiDefBut(block, TEX, B_MODIFIER_REDRAW, "", x+10, y-1, buttonWidth-60, 19, md->name, 0.0, sizeof(md->name)-1, 0.0, 0.0, "Modifier name"); /* Softbody not allowed in this situation, enforce! */ - if ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) { + if (((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) && (md->type!=eModifierType_Surface)) { uiDefIconButBitI(block, TOG, eModifierMode_Render, B_MODIFIER_RECALC, ICON_SCENE, x+10+buttonWidth-60, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during rendering"); but= uiDefIconButBitI(block, TOG, eModifierMode_Realtime, B_MODIFIER_RECALC, VICON_VIEW3D, x+10+buttonWidth-40, y-1, 19, 19,&md->mode, 0, 0, 1, 0, "Enable modifier during interactive display"); if (mti->flags&eModifierTypeFlag_SupportsEditmode) { @@ -1813,7 +1813,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco // deletion over the deflection panel // fluid particle modifier can't be deleted here - if(md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Collision && !modifier_is_fluid_particles(md)) + if(md->type!=eModifierType_Fluidsim && md->type!=eModifierType_Collision && md->type!=eModifierType_Surface && !modifier_is_fluid_particles(md)) { but = uiDefIconBut(block, BUT, B_MODIFIER_RECALC, VICON_X, x+width-70+40, y, 16, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Delete modifier"); uiButSetFunc(but, modifiers_del, ob, md); @@ -1884,6 +1884,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco height = 31; } else if (md->type==eModifierType_Collision) { height = 31; + } else if (md->type==eModifierType_Surface) { + height = 31; } else if (md->type==eModifierType_Fluidsim) { height = 31; } else if (md->type==eModifierType_Boolean) { @@ -1924,7 +1926,7 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco y -= 18; - if (!isVirtual && (md->type!=eModifierType_Collision)) { + if (!isVirtual && (md->type!=eModifierType_Collision) && (md->type!=eModifierType_Surface)) { uiSetButLock(object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); /* only here obdata, the rest of modifiers is ob level */ uiBlockBeginAlign(block); @@ -2369,6 +2371,8 @@ static void draw_modifier(uiBlock *block, Object *ob, ModifierData *md, int *xco } else if (md->type==eModifierType_Collision) { uiDefBut(block, LABEL, 1, "See Collision panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, ""); + } else if (md->type==eModifierType_Surface) { + uiDefBut(block, LABEL, 1, "See Fields panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, ""); } else if (md->type==eModifierType_Fluidsim) { uiDefBut(block, LABEL, 1, "See Fluidsim panel.", lx, (cy-=19), buttonWidth,19, NULL, 0.0, 0.0, 0, 0, ""); } else if (md->type==eModifierType_Boolean) { diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c index 5c41390b150..7fc504ba8d3 100644 --- a/source/blender/src/buttons_object.c +++ b/source/blender/src/buttons_object.c @@ -3340,6 +3340,35 @@ static void object_panel_collision(Object *ob) } } } +static void object_surface__enabletoggle ( void *ob_v, void *arg2 ) +{ + Object *ob = ob_v; + PartDeflect *pd= ob->pd; + ModifierData *md = modifiers_findByType ( ob, eModifierType_Surface ); + + if(!md) + { + if(pd && (pd->flag & PFIELD_SURFACE) + && ELEM5(pd->forcefield,PFIELD_HARMONIC,PFIELD_FORCE,PFIELD_HARMONIC,PFIELD_CHARGE,PFIELD_LENNARDJ)) + { + md = modifier_new ( eModifierType_Surface ); + BLI_addtail ( &ob->modifiers, md ); + DAG_scene_sort(G.scene); + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + allqueue(REDRAWBUTSEDIT, 0); + allqueue(REDRAWVIEW3D, 0); + } + } + else if(!pd || !(pd->flag & PFIELD_SURFACE) + || ELEM5(pd->forcefield,PFIELD_HARMONIC,PFIELD_FORCE,PFIELD_HARMONIC,PFIELD_CHARGE,PFIELD_LENNARDJ)) + { + DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA); + BLI_remlink ( &ob->modifiers, md ); + modifier_free ( md ); + DAG_scene_sort(G.scene); + allqueue(REDRAWBUTSEDIT, 0); + } +} static void object_panel_fields(Object *ob) { uiBlock *block; @@ -3425,9 +3454,12 @@ static void object_panel_fields(Object *ob) } if(ob->particlesystem.first) - uiDefButS(block, MENU, B_FIELD_DEP, menustr, 80,180,70,20, &pd->forcefield, 0.0, 0.0, 0, 0, tipstr); + but = uiDefButS(block, MENU, B_FIELD_DEP, menustr, 80,180,70,20, &pd->forcefield, 0.0, 0.0, 0, 0, tipstr); else - uiDefButS(block, MENU, B_FIELD_DEP, menustr, 10,180,140,20, &pd->forcefield, 0.0, 0.0, 0, 0, tipstr); + but = uiDefButS(block, MENU, B_FIELD_DEP, menustr, 10,180,140,20, &pd->forcefield, 0.0, 0.0, 0, 0, tipstr); + + if(!particles) + uiButSetFunc(but, object_surface__enabletoggle, ob, NULL); uiBlockEndAlign(block); uiDefBut(block, LABEL, 0, "",160,180,150,2, NULL, 0.0, 0, 0, 0, ""); @@ -3472,7 +3504,12 @@ static void object_panel_fields(Object *ob) } else if(particles==0 && ELEM(pd->forcefield,PFIELD_VORTEX,PFIELD_WIND)==0){ //uiDefButF(block, NUM, B_FIELD_CHANGE, "Distance: ", 10,20,140,20, &pd->f_dist, 0, 1000.0, 10, 0, "Falloff power (real gravitational fallof = 2)"); - uiDefButBitS(block, TOG, PFIELD_PLANAR, B_FIELD_CHANGE, "Planar", 10,15,140,20, &pd->flag, 0.0, 0, 0, 0, "Create planar field"); + uiDefButBitS(block, TOG, PFIELD_PLANAR, B_FIELD_CHANGE, "Planar", 10,35,140,20, &pd->flag, 0.0, 0, 0, 0, "Create planar field"); + } + + if(particles==0 && ELEM5(pd->forcefield,PFIELD_HARMONIC,PFIELD_FORCE,PFIELD_HARMONIC,PFIELD_CHARGE,PFIELD_LENNARDJ)) { + but = uiDefButBitS(block, TOG, PFIELD_SURFACE, B_FIELD_CHANGE, "Surface", 10,15,140,20, &pd->flag, 0.0, 0, 0, 0, "Use closest point on surface"); + uiButSetFunc(but, object_surface__enabletoggle, ob, NULL); } uiBlockEndAlign(block); |