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.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user