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