|
Blender
V2.59
|
00001 /* effect.c 00002 * 00003 * 00004 * $Id: effect.c 38663 2011-07-24 17:44:22Z jhk $ 00005 * 00006 * ***** BEGIN GPL LICENSE BLOCK ***** 00007 * 00008 * This program is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU General Public License 00010 * as published by the Free Software Foundation; either version 2 00011 * of the License, or (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software Foundation, 00020 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00021 * 00022 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. 00023 * All rights reserved. 00024 * 00025 * The Original Code is: all of this file. 00026 * 00027 * Contributor(s): none yet. 00028 * 00029 * ***** END GPL LICENSE BLOCK ***** 00030 */ 00031 00037 #include <stddef.h> 00038 #include "BLI_storage.h" /* _LARGEFILE_SOURCE */ 00039 00040 #include <math.h> 00041 #include <stdlib.h> 00042 00043 #include "MEM_guardedalloc.h" 00044 00045 #include "DNA_curve_types.h" 00046 #include "DNA_effect_types.h" 00047 #include "DNA_group_types.h" 00048 #include "DNA_ipo_types.h" 00049 #include "DNA_key_types.h" 00050 #include "DNA_lattice_types.h" 00051 #include "DNA_listBase.h" 00052 #include "DNA_mesh_types.h" 00053 #include "DNA_meshdata_types.h" 00054 #include "DNA_material_types.h" 00055 #include "DNA_object_types.h" 00056 #include "DNA_object_force.h" 00057 #include "DNA_particle_types.h" 00058 #include "DNA_texture_types.h" 00059 #include "DNA_scene_types.h" 00060 00061 #include "BLI_math.h" 00062 #include "BLI_blenlib.h" 00063 #include "BLI_jitter.h" 00064 #include "BLI_listbase.h" 00065 #include "BLI_noise.h" 00066 #include "BLI_rand.h" 00067 #include "BLI_utildefines.h" 00068 00069 #include "PIL_time.h" 00070 00071 #include "BKE_action.h" 00072 #include "BKE_anim.h" /* needed for where_on_path */ 00073 #include "BKE_armature.h" 00074 #include "BKE_blender.h" 00075 #include "BKE_collision.h" 00076 #include "BKE_constraint.h" 00077 #include "BKE_deform.h" 00078 #include "BKE_depsgraph.h" 00079 #include "BKE_displist.h" 00080 #include "BKE_DerivedMesh.h" 00081 #include "BKE_cdderivedmesh.h" 00082 #include "BKE_effect.h" 00083 #include "BKE_global.h" 00084 #include "BKE_group.h" 00085 #include "BKE_ipo.h" 00086 #include "BKE_key.h" 00087 #include "BKE_lattice.h" 00088 #include "BKE_mesh.h" 00089 #include "BKE_material.h" 00090 #include "BKE_main.h" 00091 #include "BKE_modifier.h" 00092 #include "BKE_object.h" 00093 #include "BKE_particle.h" 00094 #include "BKE_scene.h" 00095 00096 00097 #include "RE_render_ext.h" 00098 #include "RE_shader_ext.h" 00099 00100 /* fluid sim particle import */ 00101 #ifndef DISABLE_ELBEEM 00102 #include "DNA_object_fluidsim.h" 00103 #include "LBM_fluidsim.h" 00104 #include <zlib.h> 00105 #include <string.h> 00106 #endif // DISABLE_ELBEEM 00107 00108 //XXX #include "BIF_screen.h" 00109 00110 EffectorWeights *BKE_add_effector_weights(Group *group) 00111 { 00112 EffectorWeights *weights = MEM_callocN(sizeof(EffectorWeights), "EffectorWeights"); 00113 int i; 00114 00115 for(i=0; i<NUM_PFIELD_TYPES; i++) 00116 weights->weight[i] = 1.0f; 00117 00118 weights->global_gravity = 1.0f; 00119 00120 weights->group = group; 00121 00122 return weights; 00123 } 00124 PartDeflect *object_add_collision_fields(int type) 00125 { 00126 PartDeflect *pd; 00127 00128 pd= MEM_callocN(sizeof(PartDeflect), "PartDeflect"); 00129 00130 pd->forcefield = type; 00131 pd->pdef_sbdamp = 0.1f; 00132 pd->pdef_sbift = 0.2f; 00133 pd->pdef_sboft = 0.02f; 00134 pd->seed = ((unsigned int)(ceil(PIL_check_seconds_timer()))+1) % 128; 00135 pd->f_strength = 1.0f; 00136 pd->f_damp = 1.0f; 00137 00138 /* set sensible defaults based on type */ 00139 switch(type) { 00140 case PFIELD_VORTEX: 00141 pd->shape = PFIELD_SHAPE_PLANE; 00142 break; 00143 case PFIELD_WIND: 00144 pd->shape = PFIELD_SHAPE_PLANE; 00145 pd->f_flow = 1.0f; /* realistic wind behavior */ 00146 break; 00147 case PFIELD_TEXTURE: 00148 pd->f_size = 1.0f; 00149 break; 00150 } 00151 pd->flag = PFIELD_DO_LOCATION|PFIELD_DO_ROTATION; 00152 00153 return pd; 00154 } 00155 00156 /* temporal struct, used for reading return of mesh_get_mapped_verts_nors() */ 00157 00158 typedef struct VeNoCo { 00159 float co[3], no[3]; 00160 } VeNoCo; 00161 00162 /* ***************** PARTICLES ***************** */ 00163 00164 /* deprecated, only keep this for readfile.c */ 00165 PartEff *give_parteff(Object *ob) 00166 { 00167 PartEff *paf; 00168 00169 paf= ob->effect.first; 00170 while(paf) { 00171 if(paf->type==EFF_PARTICLE) return paf; 00172 paf= paf->next; 00173 } 00174 return NULL; 00175 } 00176 00177 void free_effect(Effect *eff) 00178 { 00179 PartEff *paf; 00180 00181 if(eff->type==EFF_PARTICLE) { 00182 paf= (PartEff *)eff; 00183 if(paf->keys) MEM_freeN(paf->keys); 00184 } 00185 MEM_freeN(eff); 00186 } 00187 00188 00189 void free_effects(ListBase *lb) 00190 { 00191 Effect *eff; 00192 00193 eff= lb->first; 00194 while(eff) { 00195 BLI_remlink(lb, eff); 00196 free_effect(eff); 00197 eff= lb->first; 00198 } 00199 } 00200 00201 /* -------------------------- Effectors ------------------ */ 00202 void free_partdeflect(PartDeflect *pd) 00203 { 00204 if(!pd) 00205 return; 00206 00207 if(pd->tex) 00208 pd->tex->id.us--; 00209 00210 if(pd->rng) 00211 rng_free(pd->rng); 00212 00213 MEM_freeN(pd); 00214 } 00215 00216 static void precalculate_effector(EffectorCache *eff) 00217 { 00218 unsigned int cfra = (unsigned int)(eff->scene->r.cfra >= 0 ? eff->scene->r.cfra : -eff->scene->r.cfra); 00219 if(!eff->pd->rng) 00220 eff->pd->rng = rng_new(eff->pd->seed + cfra); 00221 else 00222 rng_srandom(eff->pd->rng, eff->pd->seed + cfra); 00223 00224 if(eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type==OB_CURVE) { 00225 Curve *cu= eff->ob->data; 00226 if(cu->flag & CU_PATH) { 00227 if(cu->path==NULL || cu->path->data==NULL) 00228 makeDispListCurveTypes(eff->scene, eff->ob, 0); 00229 00230 if(cu->path && cu->path->data) { 00231 where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL); 00232 mul_m4_v3(eff->ob->obmat, eff->guide_loc); 00233 mul_mat3_m4_v3(eff->ob->obmat, eff->guide_dir); 00234 } 00235 } 00236 } 00237 else if(eff->pd->shape == PFIELD_SHAPE_SURFACE) { 00238 eff->surmd = (SurfaceModifierData *)modifiers_findByType ( eff->ob, eModifierType_Surface ); 00239 if(eff->ob->type == OB_CURVE) 00240 eff->flag |= PE_USE_NORMAL_DATA; 00241 } 00242 else if(eff->psys) 00243 psys_update_particle_tree(eff->psys, eff->scene->r.cfra); 00244 00245 /* Store object velocity */ 00246 if(eff->ob) { 00247 float old_vel[3]; 00248 00249 where_is_object_time(eff->scene, eff->ob, cfra - 1.0f); 00250 copy_v3_v3(old_vel, eff->ob->obmat[3]); 00251 where_is_object_time(eff->scene, eff->ob, cfra); 00252 sub_v3_v3v3(eff->velocity, eff->ob->obmat[3], old_vel); 00253 } 00254 } 00255 static EffectorCache *new_effector_cache(Scene *scene, Object *ob, ParticleSystem *psys, PartDeflect *pd) 00256 { 00257 EffectorCache *eff = MEM_callocN(sizeof(EffectorCache), "EffectorCache"); 00258 eff->scene = scene; 00259 eff->ob = ob; 00260 eff->psys = psys; 00261 eff->pd = pd; 00262 eff->frame = -1; 00263 00264 precalculate_effector(eff); 00265 00266 return eff; 00267 } 00268 static void add_object_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src) 00269 { 00270 EffectorCache *eff = NULL; 00271 00272 if( ob == ob_src || weights->weight[ob->pd->forcefield] == 0.0f ) 00273 return; 00274 00275 if (ob->pd->shape == PFIELD_SHAPE_POINTS && !ob->derivedFinal ) 00276 return; 00277 00278 if(*effectors == NULL) 00279 *effectors = MEM_callocN(sizeof(ListBase), "effectors list"); 00280 00281 eff = new_effector_cache(scene, ob, NULL, ob->pd); 00282 00283 /* make sure imat is up to date */ 00284 invert_m4_m4(ob->imat, ob->obmat); 00285 00286 BLI_addtail(*effectors, eff); 00287 } 00288 static void add_particles_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src) 00289 { 00290 ParticleSettings *part= psys->part; 00291 00292 if( !psys_check_enabled(ob, psys) ) 00293 return; 00294 00295 if( psys == psys_src && (part->flag & PART_SELF_EFFECT) == 0) 00296 return; 00297 00298 if( part->pd && part->pd->forcefield && weights->weight[part->pd->forcefield] != 0.0f) { 00299 if(*effectors == NULL) 00300 *effectors = MEM_callocN(sizeof(ListBase), "effectors list"); 00301 00302 BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd)); 00303 } 00304 00305 if (part->pd2 && part->pd2->forcefield && weights->weight[part->pd2->forcefield] != 0.0f) { 00306 if(*effectors == NULL) 00307 *effectors = MEM_callocN(sizeof(ListBase), "effectors list"); 00308 00309 BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd2)); 00310 } 00311 } 00312 00313 /* returns ListBase handle with objects taking part in the effecting */ 00314 ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src, EffectorWeights *weights) 00315 { 00316 Base *base; 00317 unsigned int layer= ob_src->lay; 00318 ListBase *effectors = NULL; 00319 00320 if(weights->group) { 00321 GroupObject *go; 00322 00323 for(go= weights->group->gobject.first; go; go= go->next) { 00324 if( (go->ob->lay & layer) ) { 00325 if( go->ob->pd && go->ob->pd->forcefield ) 00326 add_object_to_effectors(&effectors, scene, weights, go->ob, ob_src); 00327 00328 if( go->ob->particlesystem.first ) { 00329 ParticleSystem *psys= go->ob->particlesystem.first; 00330 00331 for( ; psys; psys=psys->next ) 00332 add_particles_to_effectors(&effectors, scene, weights, go->ob, psys, psys_src); 00333 } 00334 } 00335 } 00336 } 00337 else { 00338 for(base = scene->base.first; base; base= base->next) { 00339 if( (base->lay & layer) ) { 00340 if( base->object->pd && base->object->pd->forcefield ) 00341 add_object_to_effectors(&effectors, scene, weights, base->object, ob_src); 00342 00343 if( base->object->particlesystem.first ) { 00344 ParticleSystem *psys= base->object->particlesystem.first; 00345 00346 for( ; psys; psys=psys->next ) 00347 add_particles_to_effectors(&effectors, scene, weights, base->object, psys, psys_src); 00348 } 00349 } 00350 } 00351 } 00352 return effectors; 00353 } 00354 00355 void pdEndEffectors(ListBase **effectors) 00356 { 00357 if(*effectors) { 00358 EffectorCache *eff = (*effectors)->first; 00359 00360 for(; eff; eff=eff->next) { 00361 if(eff->guide_data) 00362 MEM_freeN(eff->guide_data); 00363 } 00364 00365 BLI_freelistN(*effectors); 00366 MEM_freeN(*effectors); 00367 *effectors = NULL; 00368 } 00369 } 00370 00371 00372 void pd_point_from_particle(ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, EffectedPoint *point) 00373 { 00374 ParticleSettings *part = sim->psys->part; 00375 point->loc = state->co; 00376 point->vel = state->vel; 00377 point->index = pa - sim->psys->particles; 00378 point->size = pa->size; 00379 point->charge = 0.0f; 00380 00381 if(part->pd && part->pd->forcefield == PFIELD_CHARGE) 00382 point->charge += part->pd->f_strength; 00383 00384 if(part->pd2 && part->pd2->forcefield == PFIELD_CHARGE) 00385 point->charge += part->pd2->f_strength; 00386 00387 point->vel_to_sec = 1.0f; 00388 point->vel_to_frame = psys_get_timestep(sim); 00389 00390 point->flag = 0; 00391 00392 if(sim->psys->part->flag & PART_ROT_DYN) { 00393 point->ave = state->ave; 00394 point->rot = state->rot; 00395 } 00396 else 00397 point->ave = point->rot = NULL; 00398 00399 point->psys = sim->psys; 00400 } 00401 00402 void pd_point_from_loc(Scene *scene, float *loc, float *vel, int index, EffectedPoint *point) 00403 { 00404 point->loc = loc; 00405 point->vel = vel; 00406 point->index = index; 00407 point->size = 0.0f; 00408 00409 point->vel_to_sec = (float)scene->r.frs_sec; 00410 point->vel_to_frame = 1.0f; 00411 00412 point->flag = 0; 00413 00414 point->ave = point->rot = NULL; 00415 point->psys = NULL; 00416 } 00417 void pd_point_from_soft(Scene *scene, float *loc, float *vel, int index, EffectedPoint *point) 00418 { 00419 point->loc = loc; 00420 point->vel = vel; 00421 point->index = index; 00422 point->size = 0.0f; 00423 00424 point->vel_to_sec = (float)scene->r.frs_sec; 00425 point->vel_to_frame = 1.0f; 00426 00427 point->flag = PE_WIND_AS_SPEED; 00428 00429 point->ave = point->rot = NULL; 00430 00431 point->psys = NULL; 00432 } 00433 /************************************************/ 00434 /* Effectors */ 00435 /************************************************/ 00436 00437 // triangle - ray callback function 00438 static void eff_tri_ray_hit(void *UNUSED(userData), int UNUSED(index), const BVHTreeRay *UNUSED(ray), BVHTreeRayHit *hit) 00439 { 00440 // whenever we hit a bounding box, we don't check further 00441 hit->dist = -1; 00442 hit->index = 1; 00443 } 00444 00445 // get visibility of a wind ray 00446 static float eff_calc_visibility(ListBase *colliders, EffectorCache *eff, EffectorData *efd, EffectedPoint *point) 00447 { 00448 ListBase *colls = colliders; 00449 ColliderCache *col; 00450 float norm[3], len = 0.0; 00451 float visibility = 1.0, absorption = 0.0; 00452 00453 if(!(eff->pd->flag & PFIELD_VISIBILITY)) 00454 return visibility; 00455 00456 if(!colls) 00457 colls = get_collider_cache(eff->scene, eff->ob, NULL); 00458 00459 if(!colls) 00460 return visibility; 00461 00462 negate_v3_v3(norm, efd->vec_to_point); 00463 len = normalize_v3(norm); 00464 00465 // check all collision objects 00466 for(col = colls->first; col; col = col->next) 00467 { 00468 CollisionModifierData *collmd = col->collmd; 00469 00470 if(col->ob == eff->ob) 00471 continue; 00472 00473 if(collmd->bvhtree) 00474 { 00475 BVHTreeRayHit hit; 00476 00477 hit.index = -1; 00478 hit.dist = len + FLT_EPSILON; 00479 00480 // check if the way is blocked 00481 if(BLI_bvhtree_ray_cast(collmd->bvhtree, point->loc, norm, 0.0f, &hit, eff_tri_ray_hit, NULL)>=0) 00482 { 00483 absorption= col->ob->pd->absorption; 00484 00485 // visibility is only between 0 and 1, calculated from 1-absorption 00486 visibility *= CLAMPIS(1.0f-absorption, 0.0f, 1.0f); 00487 00488 if(visibility <= 0.0f) 00489 break; 00490 } 00491 } 00492 } 00493 00494 if(!colliders) 00495 free_collider_cache(&colls); 00496 00497 return visibility; 00498 } 00499 00500 // noise function for wind e.g. 00501 static float wind_func(struct RNG *rng, float strength) 00502 { 00503 int random = (rng_getInt(rng)+1) % 128; // max 2357 00504 float force = rng_getFloat(rng) + 1.0f; 00505 float ret; 00506 float sign = 0; 00507 00508 sign = ((float)random > 64.0f) ? 1.0f: -1.0f; // dividing by 2 is not giving equal sign distribution 00509 00510 ret = sign*((float)random / force)*strength/128.0f; 00511 00512 return ret; 00513 } 00514 00515 /* maxdist: zero effect from this distance outwards (if usemax) */ 00516 /* mindist: full effect up to this distance (if usemin) */ 00517 /* power: falloff with formula 1/r^power */ 00518 static float falloff_func(float fac, int usemin, float mindist, int usemax, float maxdist, float power) 00519 { 00520 /* first quick checks */ 00521 if(usemax && fac > maxdist) 00522 return 0.0f; 00523 00524 if(usemin && fac < mindist) 00525 return 1.0f; 00526 00527 if(!usemin) 00528 mindist = 0.0; 00529 00530 return pow((double)(1.0f+fac-mindist), (double)(-power)); 00531 } 00532 00533 static float falloff_func_dist(PartDeflect *pd, float fac) 00534 { 00535 return falloff_func(fac, pd->flag&PFIELD_USEMIN, pd->mindist, pd->flag&PFIELD_USEMAX, pd->maxdist, pd->f_power); 00536 } 00537 00538 static float falloff_func_rad(PartDeflect *pd, float fac) 00539 { 00540 return falloff_func(fac, pd->flag&PFIELD_USEMINR, pd->minrad, pd->flag&PFIELD_USEMAXR, pd->maxrad, pd->f_power_r); 00541 } 00542 00543 float effector_falloff(EffectorCache *eff, EffectorData *efd, EffectedPoint *UNUSED(point), EffectorWeights *weights) 00544 { 00545 float temp[3]; 00546 float falloff = weights ? weights->weight[0] * weights->weight[eff->pd->forcefield] : 1.0f; 00547 float fac, r_fac; 00548 00549 fac = dot_v3v3(efd->nor, efd->vec_to_point2); 00550 00551 if(eff->pd->zdir == PFIELD_Z_POS && fac < 0.0f) 00552 falloff=0.0f; 00553 else if(eff->pd->zdir == PFIELD_Z_NEG && fac > 0.0f) 00554 falloff=0.0f; 00555 else switch(eff->pd->falloff){ 00556 case PFIELD_FALL_SPHERE: 00557 falloff*= falloff_func_dist(eff->pd, efd->distance); 00558 break; 00559 00560 case PFIELD_FALL_TUBE: 00561 falloff*= falloff_func_dist(eff->pd, ABS(fac)); 00562 if(falloff == 0.0f) 00563 break; 00564 00565 VECADDFAC(temp, efd->vec_to_point, efd->nor, -fac); 00566 r_fac= len_v3(temp); 00567 falloff*= falloff_func_rad(eff->pd, r_fac); 00568 break; 00569 case PFIELD_FALL_CONE: 00570 falloff*= falloff_func_dist(eff->pd, ABS(fac)); 00571 if(falloff == 0.0f) 00572 break; 00573 00574 r_fac=saacos(fac/len_v3(efd->vec_to_point))*180.0f/(float)M_PI; 00575 falloff*= falloff_func_rad(eff->pd, r_fac); 00576 00577 break; 00578 } 00579 00580 return falloff; 00581 } 00582 00583 int closest_point_on_surface(SurfaceModifierData *surmd, float *co, float *surface_co, float *surface_nor, float *surface_vel) 00584 { 00585 BVHTreeNearest nearest; 00586 00587 nearest.index = -1; 00588 nearest.dist = FLT_MAX; 00589 00590 BLI_bvhtree_find_nearest(surmd->bvhtree->tree, co, &nearest, surmd->bvhtree->nearest_callback, surmd->bvhtree); 00591 00592 if(nearest.index != -1) { 00593 VECCOPY(surface_co, nearest.co); 00594 00595 if(surface_nor) { 00596 VECCOPY(surface_nor, nearest.no); 00597 } 00598 00599 if(surface_vel) { 00600 MFace *mface = CDDM_get_face(surmd->dm, nearest.index); 00601 00602 VECCOPY(surface_vel, surmd->v[mface->v1].co); 00603 add_v3_v3(surface_vel, surmd->v[mface->v2].co); 00604 add_v3_v3(surface_vel, surmd->v[mface->v3].co); 00605 if(mface->v4) 00606 add_v3_v3(surface_vel, surmd->v[mface->v4].co); 00607 00608 mul_v3_fl(surface_vel, mface->v4 ? 0.25f : 0.333f); 00609 } 00610 return 1; 00611 } 00612 00613 return 0; 00614 } 00615 int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int real_velocity) 00616 { 00617 float cfra = eff->scene->r.cfra; 00618 int ret = 0; 00619 00620 if(eff->pd && eff->pd->shape==PFIELD_SHAPE_SURFACE && eff->surmd) { 00621 /* closest point in the object surface is an effector */ 00622 float vec[3]; 00623 00624 /* using velocity corrected location allows for easier sliding over effector surface */ 00625 copy_v3_v3(vec, point->vel); 00626 mul_v3_fl(vec, point->vel_to_frame); 00627 add_v3_v3(vec, point->loc); 00628 00629 ret = closest_point_on_surface(eff->surmd, vec, efd->loc, efd->nor, real_velocity ? efd->vel : NULL); 00630 00631 efd->size = 0.0f; 00632 } 00633 else if(eff->pd && eff->pd->shape==PFIELD_SHAPE_POINTS) { 00634 00635 if(eff->ob->derivedFinal) { 00636 DerivedMesh *dm = eff->ob->derivedFinal; 00637 00638 dm->getVertCo(dm, *efd->index, efd->loc); 00639 dm->getVertNo(dm, *efd->index, efd->nor); 00640 00641 mul_m4_v3(eff->ob->obmat, efd->loc); 00642 mul_mat3_m4_v3(eff->ob->obmat, efd->nor); 00643 00644 normalize_v3(efd->nor); 00645 00646 efd->size = 0.0f; 00647 00648 00649 ret = 1; 00650 } 00651 } 00652 else if(eff->psys) { 00653 ParticleData *pa = eff->psys->particles + *efd->index; 00654 ParticleKey state; 00655 00656 /* exclude the particle itself for self effecting particles */ 00657 if(eff->psys == point->psys && *efd->index == point->index) 00658 ; 00659 else { 00660 ParticleSimulationData sim= {NULL}; 00661 sim.scene= eff->scene; 00662 sim.ob= eff->ob; 00663 sim.psys= eff->psys; 00664 00665 /* TODO: time from actual previous calculated frame (step might not be 1) */ 00666 state.time = cfra - 1.0f; 00667 ret = psys_get_particle_state(&sim, *efd->index, &state, 0); 00668 00669 /* TODO */ 00670 //if(eff->pd->forcefiled == PFIELD_HARMONIC && ret==0) { 00671 // if(pa->dietime < eff->psys->cfra) 00672 // eff->flag |= PE_VELOCITY_TO_IMPULSE; 00673 //} 00674 00675 copy_v3_v3(efd->loc, state.co); 00676 00677 /* rather than use the velocity use rotated x-axis (defaults to velocity) */ 00678 efd->nor[0] = 1.f; 00679 efd->nor[1] = efd->nor[2] = 0.f; 00680 mul_qt_v3(state.rot, efd->nor); 00681 00682 if(real_velocity) 00683 copy_v3_v3(efd->vel, state.vel); 00684 00685 efd->size = pa->size; 00686 } 00687 } 00688 else { 00689 /* use center of object for distance calculus */ 00690 Object *ob = eff->ob; 00691 Object obcopy = *ob; 00692 00693 /* use z-axis as normal*/ 00694 normalize_v3_v3(efd->nor, ob->obmat[2]); 00695 00696 if(eff->pd && eff->pd->shape == PFIELD_SHAPE_PLANE) { 00697 float temp[3], translate[3]; 00698 sub_v3_v3v3(temp, point->loc, ob->obmat[3]); 00699 project_v3_v3v3(translate, temp, efd->nor); 00700 00701 /* for vortex the shape chooses between old / new force */ 00702 if(eff->pd->forcefield == PFIELD_VORTEX) 00703 add_v3_v3v3(efd->loc, ob->obmat[3], translate); 00704 else /* normally efd->loc is closest point on effector xy-plane */ 00705 sub_v3_v3v3(efd->loc, point->loc, translate); 00706 } 00707 else { 00708 VECCOPY(efd->loc, ob->obmat[3]); 00709 } 00710 00711 if(real_velocity) 00712 copy_v3_v3(efd->vel, eff->velocity); 00713 00714 *eff->ob = obcopy; 00715 00716 efd->size = 0.0f; 00717 00718 ret = 1; 00719 } 00720 00721 if(ret) { 00722 sub_v3_v3v3(efd->vec_to_point, point->loc, efd->loc); 00723 efd->distance = len_v3(efd->vec_to_point); 00724 00725 /* rest length for harmonic effector, will have to see later if this could be extended to other effectors */ 00726 if(eff->pd && eff->pd->forcefield == PFIELD_HARMONIC && eff->pd->f_size) 00727 mul_v3_fl(efd->vec_to_point, (efd->distance-eff->pd->f_size)/efd->distance); 00728 00729 if(eff->flag & PE_USE_NORMAL_DATA) { 00730 VECCOPY(efd->vec_to_point2, efd->vec_to_point); 00731 VECCOPY(efd->nor2, efd->nor); 00732 } 00733 else { 00734 /* for some effectors we need the object center every time */ 00735 sub_v3_v3v3(efd->vec_to_point2, point->loc, eff->ob->obmat[3]); 00736 normalize_v3_v3(efd->nor2, eff->ob->obmat[2]); 00737 } 00738 } 00739 00740 return ret; 00741 } 00742 static void get_effector_tot(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, int *tot, int *p, int *step) 00743 { 00744 if(eff->pd->shape == PFIELD_SHAPE_POINTS) { 00745 efd->index = p; 00746 00747 *p = 0; 00748 *tot = eff->ob->derivedFinal ? eff->ob->derivedFinal->numVertData : 1; 00749 00750 if(*tot && eff->pd->forcefield == PFIELD_HARMONIC && point->index >= 0) { 00751 *p = point->index % *tot; 00752 *tot = *p+1; 00753 } 00754 } 00755 else if(eff->psys) { 00756 efd->index = p; 00757 00758 *p = 0; 00759 *tot = eff->psys->totpart; 00760 00761 if(eff->pd->forcefield == PFIELD_CHARGE) { 00762 /* Only the charge of the effected particle is used for 00763 interaction, not fall-offs. If the fall-offs aren't the 00764 same this will be unphysical, but for animation this 00765 could be the wanted behavior. If you want physical 00766 correctness the fall-off should be spherical 2.0 anyways. 00767 */ 00768 efd->charge = eff->pd->f_strength; 00769 } 00770 else if(eff->pd->forcefield == PFIELD_HARMONIC && (eff->pd->flag & PFIELD_MULTIPLE_SPRINGS)==0) { 00771 /* every particle is mapped to only one harmonic effector particle */ 00772 *p= point->index % eff->psys->totpart; 00773 *tot= *p + 1; 00774 } 00775 00776 if(eff->psys->part->effector_amount) { 00777 int totpart = eff->psys->totpart; 00778 int amount = eff->psys->part->effector_amount; 00779 00780 *step = (totpart > amount) ? totpart/amount : 1; 00781 } 00782 } 00783 else { 00784 *p = 0; 00785 *tot = 1; 00786 } 00787 } 00788 static void do_texture_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, float *total_force) 00789 { 00790 TexResult result[4]; 00791 float tex_co[3], strength, force[3]; 00792 float nabla = eff->pd->tex_nabla; 00793 int hasrgb; 00794 short mode = eff->pd->tex_mode; 00795 00796 if(!eff->pd->tex) 00797 return; 00798 00799 result[0].nor = result[1].nor = result[2].nor = result[3].nor = NULL; 00800 00801 strength= eff->pd->f_strength * efd->falloff; 00802 00803 VECCOPY(tex_co,point->loc); 00804 00805 if(eff->pd->flag & PFIELD_TEX_2D) { 00806 float fac=-dot_v3v3(tex_co, efd->nor); 00807 VECADDFAC(tex_co, tex_co, efd->nor, fac); 00808 } 00809 00810 if(eff->pd->flag & PFIELD_TEX_OBJECT) { 00811 mul_m4_v3(eff->ob->imat, tex_co); 00812 } 00813 00814 hasrgb = multitex_ext(eff->pd->tex, tex_co, NULL,NULL, 0, result); 00815 00816 if(hasrgb && mode==PFIELD_TEX_RGB) { 00817 force[0] = (0.5f - result->tr) * strength; 00818 force[1] = (0.5f - result->tg) * strength; 00819 force[2] = (0.5f - result->tb) * strength; 00820 } 00821 else { 00822 strength/=nabla; 00823 00824 tex_co[0] += nabla; 00825 multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+1); 00826 00827 tex_co[0] -= nabla; 00828 tex_co[1] += nabla; 00829 multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+2); 00830 00831 tex_co[1] -= nabla; 00832 tex_co[2] += nabla; 00833 multitex_ext(eff->pd->tex, tex_co, NULL, NULL, 0, result+3); 00834 00835 if(mode == PFIELD_TEX_GRAD || !hasrgb) { /* if we dont have rgb fall back to grad */ 00836 force[0] = (result[0].tin - result[1].tin) * strength; 00837 force[1] = (result[0].tin - result[2].tin) * strength; 00838 force[2] = (result[0].tin - result[3].tin) * strength; 00839 } 00840 else { /*PFIELD_TEX_CURL*/ 00841 float dbdy, dgdz, drdz, dbdx, dgdx, drdy; 00842 00843 dbdy = result[2].tb - result[0].tb; 00844 dgdz = result[3].tg - result[0].tg; 00845 drdz = result[3].tr - result[0].tr; 00846 dbdx = result[1].tb - result[0].tb; 00847 dgdx = result[1].tg - result[0].tg; 00848 drdy = result[2].tr - result[0].tr; 00849 00850 force[0] = (dbdy - dgdz) * strength; 00851 force[1] = (drdz - dbdx) * strength; 00852 force[2] = (dgdx - drdy) * strength; 00853 } 00854 } 00855 00856 if(eff->pd->flag & PFIELD_TEX_2D){ 00857 float fac = -dot_v3v3(force, efd->nor); 00858 VECADDFAC(force, force, efd->nor, fac); 00859 } 00860 00861 add_v3_v3(total_force, force); 00862 } 00863 static void do_physical_effector(EffectorCache *eff, EffectorData *efd, EffectedPoint *point, float *total_force) 00864 { 00865 PartDeflect *pd = eff->pd; 00866 RNG *rng = pd->rng; 00867 float force[3]={0,0,0}; 00868 float temp[3]; 00869 float fac; 00870 float strength = pd->f_strength; 00871 float damp = pd->f_damp; 00872 float noise_factor = pd->f_noise; 00873 00874 if(noise_factor > 0.0f) { 00875 strength += wind_func(rng, noise_factor); 00876 00877 if(ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG)) 00878 damp += wind_func(rng, noise_factor); 00879 } 00880 00881 VECCOPY(force, efd->vec_to_point); 00882 00883 switch(pd->forcefield){ 00884 case PFIELD_WIND: 00885 VECCOPY(force, efd->nor); 00886 mul_v3_fl(force, strength * efd->falloff); 00887 break; 00888 case PFIELD_FORCE: 00889 normalize_v3(force); 00890 mul_v3_fl(force, strength * efd->falloff); 00891 break; 00892 case PFIELD_VORTEX: 00893 /* old vortex force */ 00894 if(pd->shape == PFIELD_SHAPE_POINT) { 00895 cross_v3_v3v3(force, efd->nor, efd->vec_to_point); 00896 normalize_v3(force); 00897 mul_v3_fl(force, strength * efd->distance * efd->falloff); 00898 } 00899 else { 00900 /* new vortex force */ 00901 cross_v3_v3v3(temp, efd->nor2, efd->vec_to_point2); 00902 mul_v3_fl(temp, strength * efd->falloff); 00903 00904 cross_v3_v3v3(force, efd->nor2, temp); 00905 mul_v3_fl(force, strength * efd->falloff); 00906 00907 VECADDFAC(temp, temp, point->vel, -point->vel_to_sec); 00908 add_v3_v3(force, temp); 00909 } 00910 break; 00911 case PFIELD_MAGNET: 00912 if(eff->pd->shape == PFIELD_SHAPE_POINT) 00913 /* magnetic field of a moving charge */ 00914 cross_v3_v3v3(temp, efd->nor, efd->vec_to_point); 00915 else 00916 copy_v3_v3(temp, efd->nor); 00917 00918 normalize_v3(temp); 00919 mul_v3_fl(temp, strength * efd->falloff); 00920 cross_v3_v3v3(force, point->vel, temp); 00921 mul_v3_fl(force, point->vel_to_sec); 00922 break; 00923 case PFIELD_HARMONIC: 00924 mul_v3_fl(force, -strength * efd->falloff); 00925 copy_v3_v3(temp, point->vel); 00926 mul_v3_fl(temp, -damp * 2.0f * (float)sqrt(fabs(strength)) * point->vel_to_sec); 00927 add_v3_v3(force, temp); 00928 break; 00929 case PFIELD_CHARGE: 00930 mul_v3_fl(force, point->charge * strength * efd->falloff); 00931 break; 00932 case PFIELD_LENNARDJ: 00933 fac = pow((efd->size + point->size) / efd->distance, 6.0); 00934 00935 fac = - fac * (1.0f - fac) / efd->distance; 00936 00937 /* limit the repulsive term drastically to avoid huge forces */ 00938 fac = ((fac>2.0f) ? 2.0f : fac); 00939 00940 mul_v3_fl(force, strength * fac); 00941 break; 00942 case PFIELD_BOID: 00943 /* Boid field is handled completely in boids code. */ 00944 return; 00945 case PFIELD_TURBULENCE: 00946 if(pd->flag & PFIELD_GLOBAL_CO) { 00947 VECCOPY(temp, point->loc); 00948 } 00949 else { 00950 VECADD(temp, efd->vec_to_point2, efd->nor2); 00951 } 00952 force[0] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[0], temp[1], temp[2], 2,0,2); 00953 force[1] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[1], temp[2], temp[0], 2,0,2); 00954 force[2] = -1.0f + 2.0f * BLI_gTurbulence(pd->f_size, temp[2], temp[0], temp[1], 2,0,2); 00955 mul_v3_fl(force, strength * efd->falloff); 00956 break; 00957 case PFIELD_DRAG: 00958 VECCOPY(force, point->vel); 00959 fac = normalize_v3(force) * point->vel_to_sec; 00960 00961 strength = MIN2(strength, 2.0f); 00962 damp = MIN2(damp, 2.0f); 00963 00964 mul_v3_fl(force, -efd->falloff * fac * (strength * fac + damp)); 00965 break; 00966 } 00967 00968 if(pd->flag & PFIELD_DO_LOCATION) { 00969 VECADDFAC(total_force, total_force, force, 1.0f/point->vel_to_sec); 00970 00971 if(ELEM(pd->forcefield, PFIELD_HARMONIC, PFIELD_DRAG)==0 && pd->f_flow != 0.0f) { 00972 VECADDFAC(total_force, total_force, point->vel, -pd->f_flow * efd->falloff); 00973 } 00974 } 00975 00976 if(pd->flag & PFIELD_DO_ROTATION && point->ave && point->rot) { 00977 float xvec[3] = {1.0f, 0.0f, 0.0f}; 00978 float dave[3]; 00979 mul_qt_v3(point->rot, xvec); 00980 cross_v3_v3v3(dave, xvec, force); 00981 if(pd->f_flow != 0.0f) { 00982 VECADDFAC(dave, dave, point->ave, -pd->f_flow * efd->falloff); 00983 } 00984 add_v3_v3(point->ave, dave); 00985 } 00986 } 00987 00988 /* -------- pdDoEffectors() -------- 00989 generic force/speed system, now used for particles and softbodies 00990 scene = scene where it runs in, for time and stuff 00991 lb = listbase with objects that take part in effecting 00992 opco = global coord, as input 00993 force = force accumulator 00994 speed = actual current speed which can be altered 00995 cur_time = "external" time in frames, is constant for static particles 00996 loc_time = "local" time in frames, range <0-1> for the lifetime of particle 00997 par_layer = layer the caller is in 00998 flags = only used for softbody wind now 00999 guide = old speed of particle 01000 01001 */ 01002 void pdDoEffectors(ListBase *effectors, ListBase *colliders, EffectorWeights *weights, EffectedPoint *point, float *force, float *impulse) 01003 { 01004 /* 01005 Modifies the force on a particle according to its 01006 relation with the effector object 01007 Different kind of effectors include: 01008 Forcefields: Gravity-like attractor 01009 (force power is related to the inverse of distance to the power of a falloff value) 01010 Vortex fields: swirling effectors 01011 (particles rotate around Z-axis of the object. otherwise, same relation as) 01012 (Forcefields, but this is not done through a force/acceleration) 01013 Guide: particles on a path 01014 (particles are guided along a curve bezier or old nurbs) 01015 (is independent of other effectors) 01016 */ 01017 EffectorCache *eff; 01018 EffectorData efd; 01019 int p=0, tot = 1, step = 1; 01020 01021 /* Cycle through collected objects, get total of (1/(gravity_strength * dist^gravity_power)) */ 01022 /* Check for min distance here? (yes would be cool to add that, ton) */ 01023 01024 if(effectors) for(eff = effectors->first; eff; eff=eff->next) { 01025 /* object effectors were fully checked to be OK to evaluate! */ 01026 01027 get_effector_tot(eff, &efd, point, &tot, &p, &step); 01028 01029 for(; p<tot; p+=step) { 01030 if(get_effector_data(eff, &efd, point, 0)) { 01031 efd.falloff= effector_falloff(eff, &efd, point, weights); 01032 01033 if(efd.falloff > 0.0f) 01034 efd.falloff *= eff_calc_visibility(colliders, eff, &efd, point); 01035 01036 if(efd.falloff <= 0.0f) 01037 ; /* don't do anything */ 01038 else if(eff->pd->forcefield == PFIELD_TEXTURE) 01039 do_texture_effector(eff, &efd, point, force); 01040 else { 01041 float temp1[3]={0,0,0}, temp2[3]; 01042 VECCOPY(temp1, force); 01043 01044 do_physical_effector(eff, &efd, point, force); 01045 01046 // for softbody backward compatibility 01047 if(point->flag & PE_WIND_AS_SPEED && impulse){ 01048 VECSUB(temp2, force, temp1); 01049 VECSUB(impulse, impulse, temp2); 01050 } 01051 } 01052 } 01053 else if(eff->flag & PE_VELOCITY_TO_IMPULSE && impulse) { 01054 /* special case for harmonic effector */ 01055 VECADD(impulse, impulse, efd.vel); 01056 } 01057 } 01058 } 01059 }