|
Blender
V2.59
|
00001 /* particle_system.c 00002 * 00003 * 00004 * $Id: particle_system.c 38463 2011-07-18 02:40:54Z 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) 2007 by Janne Karhu. 00023 * All rights reserved. 00024 * 00025 * The Original Code is: all of this file. 00026 * 00027 * Contributor(s): Raul Fernandez Hernandez (Farsthary), Stephen Swhitehorn. 00028 * 00029 * ***** END GPL LICENSE BLOCK ***** 00030 */ 00031 00037 #include <stddef.h> 00038 #include "BLI_storage.h" /* _LARGEFILE_SOURCE */ 00039 00040 #include <stdlib.h> 00041 #include <math.h> 00042 #include <string.h> 00043 00044 #include "MEM_guardedalloc.h" 00045 00046 #include "DNA_anim_types.h" 00047 #include "DNA_boid_types.h" 00048 #include "DNA_particle_types.h" 00049 #include "DNA_mesh_types.h" 00050 #include "DNA_meshdata_types.h" 00051 #include "DNA_modifier_types.h" 00052 #include "DNA_object_force.h" 00053 #include "DNA_object_types.h" 00054 #include "DNA_material_types.h" 00055 #include "DNA_curve_types.h" 00056 #include "DNA_group_types.h" 00057 #include "DNA_scene_types.h" 00058 #include "DNA_texture_types.h" 00059 #include "DNA_ipo_types.h" // XXX old animation system stuff... to be removed! 00060 #include "DNA_listBase.h" 00061 00062 #include "BLI_edgehash.h" 00063 #include "BLI_rand.h" 00064 #include "BLI_jitter.h" 00065 #include "BLI_math.h" 00066 #include "BLI_blenlib.h" 00067 #include "BLI_kdtree.h" 00068 #include "BLI_kdopbvh.h" 00069 #include "BLI_listbase.h" 00070 #include "BLI_threads.h" 00071 #include "BLI_storage.h" /* For _LARGEFILE64_SOURCE; zlib needs this on some systems */ 00072 #include "BLI_utildefines.h" 00073 00074 #include "BKE_main.h" 00075 #include "BKE_animsys.h" 00076 #include "BKE_boids.h" 00077 #include "BKE_cdderivedmesh.h" 00078 #include "BKE_collision.h" 00079 #include "BKE_displist.h" 00080 #include "BKE_effect.h" 00081 #include "BKE_particle.h" 00082 #include "BKE_global.h" 00083 00084 #include "BKE_DerivedMesh.h" 00085 #include "BKE_object.h" 00086 #include "BKE_material.h" 00087 #include "BKE_cloth.h" 00088 #include "BKE_depsgraph.h" 00089 #include "BKE_lattice.h" 00090 #include "BKE_pointcache.h" 00091 #include "BKE_mesh.h" 00092 #include "BKE_modifier.h" 00093 #include "BKE_scene.h" 00094 #include "BKE_bvhutils.h" 00095 00096 #include "PIL_time.h" 00097 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 00107 #ifdef WIN32 00108 #ifndef snprintf 00109 #define snprintf _snprintf 00110 #endif 00111 #endif 00112 00113 #endif // DISABLE_ELBEEM 00114 00115 /************************************************/ 00116 /* Reacting to system events */ 00117 /************************************************/ 00118 00119 static int particles_are_dynamic(ParticleSystem *psys) { 00120 if(psys->pointcache->flag & PTCACHE_BAKED) 00121 return 0; 00122 00123 if(psys->part->type == PART_HAIR) 00124 return psys->flag & PSYS_HAIR_DYNAMICS; 00125 else 00126 return ELEM3(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID); 00127 } 00128 00129 static int psys_get_current_display_percentage(ParticleSystem *psys) 00130 { 00131 ParticleSettings *part=psys->part; 00132 00133 if((psys->renderdata && !particles_are_dynamic(psys)) /* non-dynamic particles can be rendered fully */ 00134 || (part->child_nbr && part->childtype) /* display percentage applies to children */ 00135 || (psys->pointcache->flag & PTCACHE_BAKING)) /* baking is always done with full amount */ 00136 return 100; 00137 00138 return psys->part->disp; 00139 } 00140 00141 static int tot_particles(ParticleSystem *psys, PTCacheID *pid) 00142 { 00143 if(pid && psys->pointcache->flag & PTCACHE_EXTERNAL) 00144 return pid->cache->totpoint; 00145 else if(psys->part->distr == PART_DISTR_GRID && psys->part->from != PART_FROM_VERT) 00146 return psys->part->grid_res * psys->part->grid_res * psys->part->grid_res - psys->totunexist; 00147 else 00148 return psys->part->totpart - psys->totunexist; 00149 } 00150 00151 void psys_reset(ParticleSystem *psys, int mode) 00152 { 00153 PARTICLE_P; 00154 00155 if(ELEM(mode, PSYS_RESET_ALL, PSYS_RESET_DEPSGRAPH)) { 00156 if(mode == PSYS_RESET_ALL || !(psys->flag & PSYS_EDITED)) { 00157 /* don't free if not absolutely necessary */ 00158 if(psys->totpart != tot_particles(psys, NULL)) { 00159 psys_free_particles(psys); 00160 psys->totpart= 0; 00161 } 00162 00163 psys->totkeyed= 0; 00164 psys->flag &= ~(PSYS_HAIR_DONE|PSYS_KEYED); 00165 00166 if(psys->edit && psys->free_edit) { 00167 psys->free_edit(psys->edit); 00168 psys->edit = NULL; 00169 psys->free_edit = NULL; 00170 } 00171 } 00172 } 00173 else if(mode == PSYS_RESET_CACHE_MISS) { 00174 /* set all particles to be skipped */ 00175 LOOP_PARTICLES 00176 pa->flag |= PARS_NO_DISP; 00177 } 00178 00179 /* reset children */ 00180 if(psys->child) { 00181 MEM_freeN(psys->child); 00182 psys->child= NULL; 00183 } 00184 00185 psys->totchild= 0; 00186 00187 /* reset path cache */ 00188 psys_free_path_cache(psys, psys->edit); 00189 00190 /* reset point cache */ 00191 BKE_ptcache_invalidate(psys->pointcache); 00192 00193 if(psys->fluid_springs) { 00194 MEM_freeN(psys->fluid_springs); 00195 psys->fluid_springs = NULL; 00196 } 00197 00198 psys->tot_fluidsprings = psys->alloc_fluidsprings = 0; 00199 } 00200 00201 static void realloc_particles(ParticleSimulationData *sim, int new_totpart) 00202 { 00203 ParticleSystem *psys = sim->psys; 00204 ParticleSettings *part = psys->part; 00205 ParticleData *newpars = NULL; 00206 BoidParticle *newboids = NULL; 00207 PARTICLE_P; 00208 int totpart, totsaved = 0; 00209 00210 if(new_totpart<0) { 00211 if(part->distr==PART_DISTR_GRID && part->from != PART_FROM_VERT) { 00212 totpart= part->grid_res; 00213 totpart*=totpart*totpart; 00214 } 00215 else 00216 totpart=part->totpart; 00217 } 00218 else 00219 totpart=new_totpart; 00220 00221 if(totpart != psys->totpart) { 00222 if(psys->edit && psys->free_edit) { 00223 psys->free_edit(psys->edit); 00224 psys->edit = NULL; 00225 psys->free_edit = NULL; 00226 } 00227 00228 if(totpart) { 00229 newpars= MEM_callocN(totpart*sizeof(ParticleData), "particles"); 00230 if(newpars == NULL) 00231 return; 00232 00233 if(psys->part->phystype == PART_PHYS_BOIDS) { 00234 newboids= MEM_callocN(totpart*sizeof(BoidParticle), "boid particles"); 00235 00236 if(newboids == NULL) { 00237 /* allocation error! */ 00238 if(newpars) 00239 MEM_freeN(newpars); 00240 return; 00241 } 00242 } 00243 } 00244 00245 if(psys->particles) { 00246 totsaved=MIN2(psys->totpart,totpart); 00247 /*save old pars*/ 00248 if(totsaved) { 00249 memcpy(newpars,psys->particles,totsaved*sizeof(ParticleData)); 00250 00251 if(psys->particles->boid) 00252 memcpy(newboids, psys->particles->boid, totsaved*sizeof(BoidParticle)); 00253 } 00254 00255 if(psys->particles->keys) 00256 MEM_freeN(psys->particles->keys); 00257 00258 if(psys->particles->boid) 00259 MEM_freeN(psys->particles->boid); 00260 00261 for(p=0, pa=newpars; p<totsaved; p++, pa++) { 00262 if(pa->keys) { 00263 pa->keys= NULL; 00264 pa->totkey= 0; 00265 } 00266 } 00267 00268 for(p=totsaved, pa=psys->particles+totsaved; p<psys->totpart; p++, pa++) 00269 if(pa->hair) MEM_freeN(pa->hair); 00270 00271 MEM_freeN(psys->particles); 00272 psys_free_pdd(psys); 00273 } 00274 00275 psys->particles=newpars; 00276 psys->totpart=totpart; 00277 00278 if(newboids) { 00279 LOOP_PARTICLES 00280 pa->boid = newboids++; 00281 } 00282 } 00283 00284 if(psys->child) { 00285 MEM_freeN(psys->child); 00286 psys->child=NULL; 00287 psys->totchild=0; 00288 } 00289 } 00290 00291 static int get_psys_child_number(struct Scene *scene, ParticleSystem *psys) 00292 { 00293 int nbr; 00294 00295 if(!psys->part->childtype) 00296 return 0; 00297 00298 if(psys->renderdata) 00299 nbr= psys->part->ren_child_nbr; 00300 else 00301 nbr= psys->part->child_nbr; 00302 00303 return get_render_child_particle_number(&scene->r, nbr); 00304 } 00305 00306 static int get_psys_tot_child(struct Scene *scene, ParticleSystem *psys) 00307 { 00308 return psys->totpart*get_psys_child_number(scene, psys); 00309 } 00310 00311 static void alloc_child_particles(ParticleSystem *psys, int tot) 00312 { 00313 if(psys->child){ 00314 /* only re-allocate if we have to */ 00315 if(psys->part->childtype && psys->totchild == tot) { 00316 memset(psys->child, 0, tot*sizeof(ChildParticle)); 00317 return; 00318 } 00319 00320 MEM_freeN(psys->child); 00321 psys->child=NULL; 00322 psys->totchild=0; 00323 } 00324 00325 if(psys->part->childtype) { 00326 psys->totchild= tot; 00327 if(psys->totchild) 00328 psys->child= MEM_callocN(psys->totchild*sizeof(ChildParticle), "child_particles"); 00329 } 00330 } 00331 00332 /************************************************/ 00333 /* Distribution */ 00334 /************************************************/ 00335 00336 void psys_calc_dmcache(Object *ob, DerivedMesh *dm, ParticleSystem *psys) 00337 { 00338 /* use for building derived mesh mapping info: 00339 00340 node: the allocated links - total derived mesh element count 00341 nodearray: the array of nodes aligned with the base mesh's elements, so 00342 each original elements can reference its derived elements 00343 */ 00344 Mesh *me= (Mesh*)ob->data; 00345 PARTICLE_P; 00346 00347 /* CACHE LOCATIONS */ 00348 if(!dm->deformedOnly) { 00349 /* Will use later to speed up subsurf/derivedmesh */ 00350 LinkNode *node, *nodedmelem, **nodearray; 00351 int totdmelem, totelem, i, *origindex; 00352 00353 if(psys->part->from == PART_FROM_VERT) { 00354 totdmelem= dm->getNumVerts(dm); 00355 totelem= me->totvert; 00356 origindex= dm->getVertDataArray(dm, CD_ORIGINDEX); 00357 } 00358 else { /* FROM_FACE/FROM_VOLUME */ 00359 totdmelem= dm->getNumFaces(dm); 00360 totelem= me->totface; 00361 origindex= dm->getFaceDataArray(dm, CD_ORIGINDEX); 00362 } 00363 00364 nodedmelem= MEM_callocN(sizeof(LinkNode)*totdmelem, "psys node elems"); 00365 nodearray= MEM_callocN(sizeof(LinkNode *)*totelem, "psys node array"); 00366 00367 for(i=0, node=nodedmelem; i<totdmelem; i++, origindex++, node++) { 00368 node->link= SET_INT_IN_POINTER(i); 00369 00370 if(*origindex != -1) { 00371 if(nodearray[*origindex]) { 00372 /* prepend */ 00373 node->next = nodearray[*origindex]; 00374 nodearray[*origindex]= node; 00375 } 00376 else 00377 nodearray[*origindex]= node; 00378 } 00379 } 00380 00381 /* cache the verts/faces! */ 00382 LOOP_PARTICLES { 00383 if(pa->num < 0) { 00384 pa->num_dmcache = -1; 00385 continue; 00386 } 00387 00388 if(psys->part->from == PART_FROM_VERT) { 00389 if(nodearray[pa->num]) 00390 pa->num_dmcache= GET_INT_FROM_POINTER(nodearray[pa->num]->link); 00391 } 00392 else { /* FROM_FACE/FROM_VOLUME */ 00393 /* Note that sometimes the pa->num is over the nodearray size, this is bad, maybe there is a better place to fix this, 00394 * but for now passing NULL is OK. every face will be searched for the particle so its slower - Campbell */ 00395 pa->num_dmcache= psys_particle_dm_face_lookup(ob, dm, pa->num, pa->fuv, pa->num < totelem ? nodearray[pa->num] : NULL); 00396 } 00397 } 00398 00399 MEM_freeN(nodearray); 00400 MEM_freeN(nodedmelem); 00401 } 00402 else { 00403 /* TODO PARTICLE, make the following line unnecessary, each function 00404 * should know to use the num or num_dmcache, set the num_dmcache to 00405 * an invalid value, just incase */ 00406 00407 LOOP_PARTICLES 00408 pa->num_dmcache = -1; 00409 } 00410 } 00411 00412 static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, ParticleSystem *psys) 00413 { 00414 ChildParticle *cpa = NULL; 00415 int i, p; 00416 int child_nbr= get_psys_child_number(scene, psys); 00417 int totpart= get_psys_tot_child(scene, psys); 00418 00419 alloc_child_particles(psys, totpart); 00420 00421 cpa = psys->child; 00422 for(i=0; i<child_nbr; i++){ 00423 for(p=0; p<psys->totpart; p++,cpa++){ 00424 float length=2.0; 00425 cpa->parent=p; 00426 00427 /* create even spherical distribution inside unit sphere */ 00428 while(length>=1.0f){ 00429 cpa->fuv[0]=2.0f*BLI_frand()-1.0f; 00430 cpa->fuv[1]=2.0f*BLI_frand()-1.0f; 00431 cpa->fuv[2]=2.0f*BLI_frand()-1.0f; 00432 length=len_v3(cpa->fuv); 00433 } 00434 00435 cpa->num=-1; 00436 } 00437 } 00438 /* dmcache must be updated for parent particles if children from faces is used */ 00439 psys_calc_dmcache(ob, finaldm, psys); 00440 } 00441 static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys) 00442 { 00443 ParticleData *pa=NULL; 00444 float min[3], max[3], delta[3], d; 00445 MVert *mv, *mvert = dm->getVertDataArray(dm,0); 00446 int totvert=dm->getNumVerts(dm), from=psys->part->from; 00447 int i, j, k, p, res=psys->part->grid_res, size[3], axis; 00448 00449 mv=mvert; 00450 00451 /* find bounding box of dm */ 00452 copy_v3_v3(min, mv->co); 00453 copy_v3_v3(max, mv->co); 00454 mv++; 00455 00456 for(i=1; i<totvert; i++, mv++){ 00457 min[0]=MIN2(min[0],mv->co[0]); 00458 min[1]=MIN2(min[1],mv->co[1]); 00459 min[2]=MIN2(min[2],mv->co[2]); 00460 00461 max[0]=MAX2(max[0],mv->co[0]); 00462 max[1]=MAX2(max[1],mv->co[1]); 00463 max[2]=MAX2(max[2],mv->co[2]); 00464 } 00465 00466 VECSUB(delta,max,min); 00467 00468 /* determine major axis */ 00469 axis = (delta[0]>=delta[1]) ? 0 : ((delta[1]>=delta[2]) ? 1 : 2); 00470 00471 d = delta[axis]/(float)res; 00472 00473 size[axis] = res; 00474 size[(axis+1)%3] = (int)ceil(delta[(axis+1)%3]/d); 00475 size[(axis+2)%3] = (int)ceil(delta[(axis+2)%3]/d); 00476 00477 /* float errors grrr.. */ 00478 size[(axis+1)%3] = MIN2(size[(axis+1)%3],res); 00479 size[(axis+2)%3] = MIN2(size[(axis+2)%3],res); 00480 00481 size[0] = MAX2(size[0], 1); 00482 size[1] = MAX2(size[1], 1); 00483 size[2] = MAX2(size[2], 1); 00484 00485 /* no full offset for flat/thin objects */ 00486 min[0]+= d < delta[0] ? d/2.f : delta[0]/2.f; 00487 min[1]+= d < delta[1] ? d/2.f : delta[1]/2.f; 00488 min[2]+= d < delta[2] ? d/2.f : delta[2]/2.f; 00489 00490 for(i=0,p=0,pa=psys->particles; i<res; i++){ 00491 for(j=0; j<res; j++){ 00492 for(k=0; k<res; k++,p++,pa++){ 00493 pa->fuv[0] = min[0] + (float)i*d; 00494 pa->fuv[1] = min[1] + (float)j*d; 00495 pa->fuv[2] = min[2] + (float)k*d; 00496 pa->flag |= PARS_UNEXIST; 00497 pa->hair_index = 0; /* abused in volume calculation */ 00498 } 00499 } 00500 } 00501 00502 /* enable particles near verts/edges/faces/inside surface */ 00503 if(from==PART_FROM_VERT){ 00504 float vec[3]; 00505 00506 pa=psys->particles; 00507 00508 min[0] -= d/2.0f; 00509 min[1] -= d/2.0f; 00510 min[2] -= d/2.0f; 00511 00512 for(i=0,mv=mvert; i<totvert; i++,mv++){ 00513 sub_v3_v3v3(vec,mv->co,min); 00514 vec[0]/=delta[0]; 00515 vec[1]/=delta[1]; 00516 vec[2]/=delta[2]; 00517 (pa +((int)(vec[0]*(size[0]-1))*res 00518 +(int)(vec[1]*(size[1]-1)))*res 00519 +(int)(vec[2]*(size[2]-1)))->flag &= ~PARS_UNEXIST; 00520 } 00521 } 00522 else if(ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)){ 00523 float co1[3], co2[3]; 00524 00525 MFace *mface= NULL, *mface_array; 00526 float v1[3], v2[3], v3[3], v4[4], lambda; 00527 int a, a1, a2, a0mul, a1mul, a2mul, totface; 00528 int amax= from==PART_FROM_FACE ? 3 : 1; 00529 00530 totface=dm->getNumFaces(dm); 00531 mface_array= dm->getFaceDataArray(dm,CD_MFACE); 00532 00533 for(a=0; a<amax; a++){ 00534 if(a==0){ a0mul=res*res; a1mul=res; a2mul=1; } 00535 else if(a==1){ a0mul=res; a1mul=1; a2mul=res*res; } 00536 else{ a0mul=1; a1mul=res*res; a2mul=res; } 00537 00538 for(a1=0; a1<size[(a+1)%3]; a1++){ 00539 for(a2=0; a2<size[(a+2)%3]; a2++){ 00540 mface= mface_array; 00541 00542 pa = psys->particles + a1*a1mul + a2*a2mul; 00543 copy_v3_v3(co1, pa->fuv); 00544 co1[a] -= d < delta[a] ? d/2.f : delta[a]/2.f; 00545 copy_v3_v3(co2, co1); 00546 co2[a] += delta[a] + 0.001f*d; 00547 co1[a] -= 0.001f*d; 00548 00549 /* lets intersect the faces */ 00550 for(i=0; i<totface; i++,mface++){ 00551 copy_v3_v3(v1, mvert[mface->v1].co); 00552 copy_v3_v3(v2, mvert[mface->v2].co); 00553 copy_v3_v3(v3, mvert[mface->v3].co); 00554 00555 if(isect_axial_line_tri_v3(a, co1, co2, v2, v3, v1, &lambda)){ 00556 if(from==PART_FROM_FACE) 00557 (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST; 00558 else /* store number of intersections */ 00559 (pa+(int)(lambda*size[a])*a0mul)->hair_index++; 00560 } 00561 00562 if(mface->v4){ 00563 copy_v3_v3(v4, mvert[mface->v4].co); 00564 00565 if(isect_axial_line_tri_v3(a, co1, co2, v4, v1, v3, &lambda)){ 00566 if(from==PART_FROM_FACE) 00567 (pa+(int)(lambda*size[a])*a0mul)->flag &= ~PARS_UNEXIST; 00568 else 00569 (pa+(int)(lambda*size[a])*a0mul)->hair_index++; 00570 } 00571 } 00572 } 00573 00574 if(from==PART_FROM_VOLUME){ 00575 int in=pa->hair_index%2; 00576 if(in) pa->hair_index++; 00577 for(i=0; i<size[0]; i++){ 00578 if(in || (pa+i*a0mul)->hair_index%2) 00579 (pa+i*a0mul)->flag &= ~PARS_UNEXIST; 00580 /* odd intersections == in->out / out->in */ 00581 /* even intersections -> in stays same */ 00582 in=(in + (pa+i*a0mul)->hair_index) % 2; 00583 } 00584 } 00585 } 00586 } 00587 } 00588 } 00589 00590 if(psys->part->flag & PART_GRID_HEXAGONAL) { 00591 for(i=0,p=0,pa=psys->particles; i<res; i++){ 00592 for(j=0; j<res; j++){ 00593 for(k=0; k<res; k++,p++,pa++){ 00594 if(j%2) 00595 pa->fuv[0] += d/2.f; 00596 00597 if(k%2) { 00598 pa->fuv[0] += d/2.f; 00599 pa->fuv[1] += d/2.f; 00600 } 00601 } 00602 } 00603 } 00604 } 00605 00606 if(psys->part->flag & PART_GRID_INVERT){ 00607 for(i=0; i<size[0]; i++){ 00608 for(j=0; j<size[1]; j++){ 00609 pa=psys->particles + res*(i*res + j); 00610 for(k=0; k<size[2]; k++, pa++){ 00611 pa->flag ^= PARS_UNEXIST; 00612 } 00613 } 00614 } 00615 } 00616 00617 if(psys->part->grid_rand > 0.f) { 00618 float rfac = d * psys->part->grid_rand; 00619 for(p=0,pa=psys->particles; p<psys->totpart; p++,pa++){ 00620 if(pa->flag & PARS_UNEXIST) 00621 continue; 00622 00623 pa->fuv[0] += rfac * (PSYS_FRAND(p + 31) - 0.5f); 00624 pa->fuv[1] += rfac * (PSYS_FRAND(p + 32) - 0.5f); 00625 pa->fuv[2] += rfac * (PSYS_FRAND(p + 33) - 0.5f); 00626 } 00627 } 00628 } 00629 00630 /* modified copy from rayshade.c */ 00631 static void hammersley_create(float *out, int n, int seed, float amount) 00632 { 00633 RNG *rng; 00634 double p, t, offs[2]; 00635 int k, kk; 00636 00637 rng = rng_new(31415926 + n + seed); 00638 offs[0]= rng_getDouble(rng) + (double)amount; 00639 offs[1]= rng_getDouble(rng) + (double)amount; 00640 rng_free(rng); 00641 00642 for (k = 0; k < n; k++) { 00643 t = 0; 00644 for (p = 0.5, kk = k; kk; p *= 0.5, kk >>= 1) 00645 if (kk & 1) /* kk mod 2 = 1 */ 00646 t += p; 00647 00648 out[2*k + 0]= fmod((double)k/(double)n + offs[0], 1.0); 00649 out[2*k + 1]= fmod(t + offs[1], 1.0); 00650 } 00651 } 00652 00653 /* modified copy from effect.c */ 00654 static void init_mv_jit(float *jit, int num, int seed2, float amount) 00655 { 00656 RNG *rng; 00657 float *jit2, x, rad1, rad2, rad3; 00658 int i, num2; 00659 00660 if(num==0) return; 00661 00662 rad1= (float)(1.0f/sqrtf((float)num)); 00663 rad2= (float)(1.0f/((float)num)); 00664 rad3= (float)sqrt((float)num)/((float)num); 00665 00666 rng = rng_new(31415926 + num + seed2); 00667 x= 0; 00668 num2 = 2 * num; 00669 for(i=0; i<num2; i+=2) { 00670 00671 jit[i]= x + amount*rad1*(0.5f - rng_getFloat(rng)); 00672 jit[i+1]= i/(2.0f*num) + amount*rad1*(0.5f - rng_getFloat(rng)); 00673 00674 jit[i]-= (float)floor(jit[i]); 00675 jit[i+1]-= (float)floor(jit[i+1]); 00676 00677 x+= rad3; 00678 x -= (float)floor(x); 00679 } 00680 00681 jit2= MEM_mallocN(12 + 2*sizeof(float)*num, "initjit"); 00682 00683 for (i=0 ; i<4 ; i++) { 00684 BLI_jitterate1(jit, jit2, num, rad1); 00685 BLI_jitterate1(jit, jit2, num, rad1); 00686 BLI_jitterate2(jit, jit2, num, rad2); 00687 } 00688 MEM_freeN(jit2); 00689 rng_free(rng); 00690 } 00691 00692 static void psys_uv_to_w(float u, float v, int quad, float *w) 00693 { 00694 float vert[4][3], co[3]; 00695 00696 if(!quad) { 00697 if(u+v > 1.0f) 00698 v= 1.0f-v; 00699 else 00700 u= 1.0f-u; 00701 } 00702 00703 vert[0][0]= 0.0f; vert[0][1]= 0.0f; vert[0][2]= 0.0f; 00704 vert[1][0]= 1.0f; vert[1][1]= 0.0f; vert[1][2]= 0.0f; 00705 vert[2][0]= 1.0f; vert[2][1]= 1.0f; vert[2][2]= 0.0f; 00706 00707 co[0]= u; 00708 co[1]= v; 00709 co[2]= 0.0f; 00710 00711 if(quad) { 00712 vert[3][0]= 0.0f; vert[3][1]= 1.0f; vert[3][2]= 0.0f; 00713 interp_weights_poly_v3( w,vert, 4, co); 00714 } 00715 else { 00716 interp_weights_poly_v3( w,vert, 3, co); 00717 w[3]= 0.0f; 00718 } 00719 } 00720 00721 /* Find the index in "sum" array before "value" is crossed. */ 00722 static int distribute_binary_search(float *sum, int n, float value) 00723 { 00724 int mid, low=0, high=n; 00725 00726 if(value == 0.f) 00727 return 0; 00728 00729 while(low <= high) { 00730 mid= (low + high)/2; 00731 00732 if(sum[mid] < value && value <= sum[mid+1]) 00733 return mid; 00734 00735 if(sum[mid] >= value) 00736 high= mid - 1; 00737 else if(sum[mid] < value) 00738 low= mid + 1; 00739 else 00740 return mid; 00741 } 00742 00743 return low; 00744 } 00745 00746 /* the max number if calls to rng_* funcs within psys_thread_distribute_particle 00747 * be sure to keep up to date if this changes */ 00748 #define PSYS_RND_DIST_SKIP 2 00749 00750 /* note: this function must be thread safe, for from == PART_FROM_CHILD */ 00751 #define ONLY_WORKING_WITH_PA_VERTS 0 00752 static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, ChildParticle *cpa, int p) 00753 { 00754 ParticleThreadContext *ctx= thread->ctx; 00755 Object *ob= ctx->sim.ob; 00756 DerivedMesh *dm= ctx->dm; 00757 float *v1, *v2, *v3, *v4, nor[3], orco1[3], co1[3], co2[3], nor1[3]; 00758 float cur_d, min_d, randu, randv; 00759 int from= ctx->from; 00760 int cfrom= ctx->cfrom; 00761 int distr= ctx->distr; 00762 int i, intersect, tot; 00763 int rng_skip_tot= PSYS_RND_DIST_SKIP; /* count how many rng_* calls wont need skipping */ 00764 00765 if(from == PART_FROM_VERT) { 00766 /* TODO_PARTICLE - use original index */ 00767 pa->num= ctx->index[p]; 00768 pa->fuv[0] = 1.0f; 00769 pa->fuv[1] = pa->fuv[2] = pa->fuv[3] = 0.0; 00770 00771 #if ONLY_WORKING_WITH_PA_VERTS 00772 if(ctx->tree){ 00773 KDTreeNearest ptn[3]; 00774 int w, maxw; 00775 00776 psys_particle_on_dm(ctx->dm,from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,orco1,0); 00777 transform_mesh_orco_verts((Mesh*)ob->data, &orco1, 1, 1); 00778 maxw = BLI_kdtree_find_n_nearest(ctx->tree,3,orco1,NULL,ptn); 00779 00780 for(w=0; w<maxw; w++){ 00781 pa->verts[w]=ptn->num; 00782 } 00783 } 00784 #endif 00785 } 00786 else if(from == PART_FROM_FACE || from == PART_FROM_VOLUME) { 00787 MFace *mface; 00788 00789 pa->num = i = ctx->index[p]; 00790 mface = dm->getFaceData(dm,i,CD_MFACE); 00791 00792 switch(distr){ 00793 case PART_DISTR_JIT: 00794 if(ctx->jitlevel == 1) { 00795 if(mface->v4) 00796 psys_uv_to_w(0.5f, 0.5f, mface->v4, pa->fuv); 00797 else 00798 psys_uv_to_w(0.33333f, 0.33333f, mface->v4, pa->fuv); 00799 } 00800 else { 00801 ctx->jitoff[i] = fmod(ctx->jitoff[i],(float)ctx->jitlevel); 00802 psys_uv_to_w(ctx->jit[2*(int)ctx->jitoff[i]], ctx->jit[2*(int)ctx->jitoff[i]+1], mface->v4, pa->fuv); 00803 ctx->jitoff[i]++; 00804 } 00805 break; 00806 case PART_DISTR_RAND: 00807 randu= rng_getFloat(thread->rng); 00808 randv= rng_getFloat(thread->rng); 00809 rng_skip_tot -= 2; 00810 00811 psys_uv_to_w(randu, randv, mface->v4, pa->fuv); 00812 break; 00813 } 00814 pa->foffset= 0.0f; 00815 00816 /* experimental */ 00817 if(from==PART_FROM_VOLUME){ 00818 MVert *mvert=dm->getVertDataArray(dm,CD_MVERT); 00819 00820 tot=dm->getNumFaces(dm); 00821 00822 psys_interpolate_face(mvert,mface,0,0,pa->fuv,co1,nor,0,0,0,0); 00823 00824 normalize_v3(nor); 00825 mul_v3_fl(nor,-100.0); 00826 00827 VECADD(co2,co1,nor); 00828 00829 min_d=2.0; 00830 intersect=0; 00831 00832 for(i=0,mface=dm->getFaceDataArray(dm,CD_MFACE); i<tot; i++,mface++){ 00833 if(i==pa->num) continue; 00834 00835 v1=mvert[mface->v1].co; 00836 v2=mvert[mface->v2].co; 00837 v3=mvert[mface->v3].co; 00838 00839 if(isect_line_tri_v3(co1, co2, v2, v3, v1, &cur_d, 0)){ 00840 if(cur_d<min_d){ 00841 min_d=cur_d; 00842 pa->foffset=cur_d*50.0f; /* to the middle of volume */ 00843 intersect=1; 00844 } 00845 } 00846 if(mface->v4){ 00847 v4=mvert[mface->v4].co; 00848 00849 if(isect_line_tri_v3(co1, co2, v4, v1, v3, &cur_d, 0)){ 00850 if(cur_d<min_d){ 00851 min_d=cur_d; 00852 pa->foffset=cur_d*50.0f; /* to the middle of volume */ 00853 intersect=1; 00854 } 00855 } 00856 } 00857 } 00858 if(intersect==0) 00859 pa->foffset=0.0; 00860 else switch(distr){ 00861 case PART_DISTR_JIT: 00862 pa->foffset*= ctx->jit[p%(2*ctx->jitlevel)]; 00863 break; 00864 case PART_DISTR_RAND: 00865 pa->foffset*=BLI_frand(); 00866 break; 00867 } 00868 } 00869 } 00870 else if(from == PART_FROM_CHILD) { 00871 MFace *mf; 00872 00873 if(ctx->index[p] < 0) { 00874 cpa->num=0; 00875 cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]=0.0f; 00876 cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0; 00877 return; 00878 } 00879 00880 mf= dm->getFaceData(dm, ctx->index[p], CD_MFACE); 00881 00882 randu= rng_getFloat(thread->rng); 00883 randv= rng_getFloat(thread->rng); 00884 rng_skip_tot -= 2; 00885 00886 psys_uv_to_w(randu, randv, mf->v4, cpa->fuv); 00887 00888 cpa->num = ctx->index[p]; 00889 00890 if(ctx->tree){ 00891 KDTreeNearest ptn[10]; 00892 int w,maxw;//, do_seams; 00893 float maxd /*, mind,dd */, totw= 0.0f; 00894 int parent[10]; 00895 float pweight[10]; 00896 00897 psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,NULL,NULL,orco1,NULL); 00898 transform_mesh_orco_verts((Mesh*)ob->data, &orco1, 1, 1); 00899 maxw = BLI_kdtree_find_n_nearest(ctx->tree,4,orco1,NULL,ptn); 00900 00901 maxd=ptn[maxw-1].dist; 00902 /* mind=ptn[0].dist; */ /* UNUSED */ 00903 00904 /* the weights here could be done better */ 00905 for(w=0; w<maxw; w++){ 00906 parent[w]=ptn[w].index; 00907 pweight[w]=(float)pow(2.0,(double)(-6.0f*ptn[w].dist/maxd)); 00908 } 00909 for(;w<10; w++){ 00910 parent[w]=-1; 00911 pweight[w]=0.0f; 00912 } 00913 00914 for(w=0,i=0; w<maxw && i<4; w++){ 00915 if(parent[w]>=0){ 00916 cpa->pa[i]=parent[w]; 00917 cpa->w[i]=pweight[w]; 00918 totw+=pweight[w]; 00919 i++; 00920 } 00921 } 00922 for(;i<4; i++){ 00923 cpa->pa[i]=-1; 00924 cpa->w[i]=0.0f; 00925 } 00926 00927 if(totw>0.0f) for(w=0; w<4; w++) 00928 cpa->w[w]/=totw; 00929 00930 cpa->parent=cpa->pa[0]; 00931 } 00932 } 00933 00934 if(rng_skip_tot > 0) /* should never be below zero */ 00935 rng_skip(thread->rng, rng_skip_tot); 00936 } 00937 00938 static void *distribute_threads_exec_cb(void *data) 00939 { 00940 ParticleThread *thread= (ParticleThread*)data; 00941 ParticleSystem *psys= thread->ctx->sim.psys; 00942 ParticleData *pa; 00943 ChildParticle *cpa; 00944 int p, totpart; 00945 00946 if(thread->ctx->from == PART_FROM_CHILD) { 00947 totpart= psys->totchild; 00948 cpa= psys->child; 00949 00950 for(p=0; p<totpart; p++, cpa++) { 00951 if(thread->ctx->skip) /* simplification skip */ 00952 rng_skip(thread->rng, PSYS_RND_DIST_SKIP * thread->ctx->skip[p]); 00953 00954 if((p+thread->num) % thread->tot == 0) 00955 distribute_threads_exec(thread, NULL, cpa, p); 00956 else /* thread skip */ 00957 rng_skip(thread->rng, PSYS_RND_DIST_SKIP); 00958 } 00959 } 00960 else { 00961 totpart= psys->totpart; 00962 pa= psys->particles + thread->num; 00963 for(p=thread->num; p<totpart; p+=thread->tot, pa+=thread->tot) 00964 distribute_threads_exec(thread, pa, NULL, p); 00965 } 00966 00967 return 0; 00968 } 00969 00970 /* not thread safe, but qsort doesn't take userdata argument */ 00971 static int *COMPARE_ORIG_INDEX = NULL; 00972 static int distribute_compare_orig_index(const void *p1, const void *p2) 00973 { 00974 int index1 = COMPARE_ORIG_INDEX[*(const int*)p1]; 00975 int index2 = COMPARE_ORIG_INDEX[*(const int*)p2]; 00976 00977 if(index1 < index2) 00978 return -1; 00979 else if(index1 == index2) { 00980 /* this pointer comparison appears to make qsort stable for glibc, 00981 * and apparently on solaris too, makes the renders reproducable */ 00982 if(p1 < p2) 00983 return -1; 00984 else if(p1 == p2) 00985 return 0; 00986 else 00987 return 1; 00988 } 00989 else 00990 return 1; 00991 } 00992 00993 static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from) 00994 { 00995 if(from == PART_FROM_CHILD) { 00996 ChildParticle *cpa; 00997 int p, totchild = get_psys_tot_child(scene, psys); 00998 00999 if(psys->child && totchild) { 01000 for(p=0,cpa=psys->child; p<totchild; p++,cpa++){ 01001 cpa->fuv[0]=cpa->fuv[1]=cpa->fuv[2]=cpa->fuv[3]= 0.0; 01002 cpa->foffset= 0.0f; 01003 cpa->parent=0; 01004 cpa->pa[0]=cpa->pa[1]=cpa->pa[2]=cpa->pa[3]=0; 01005 cpa->num= -1; 01006 } 01007 } 01008 } 01009 else { 01010 PARTICLE_P; 01011 LOOP_PARTICLES { 01012 pa->fuv[0]=pa->fuv[1]=pa->fuv[2]= pa->fuv[3]= 0.0; 01013 pa->foffset= 0.0f; 01014 pa->num= -1; 01015 } 01016 } 01017 } 01018 01019 /* Creates a distribution of coordinates on a DerivedMesh */ 01020 /* This is to denote functionality that does not yet work with mesh - only derived mesh */ 01021 static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, DerivedMesh *finaldm, int from) 01022 { 01023 ParticleThreadContext *ctx= threads[0].ctx; 01024 Object *ob= ctx->sim.ob; 01025 ParticleSystem *psys= ctx->sim.psys; 01026 ParticleData *pa=0, *tpars= 0; 01027 ParticleSettings *part; 01028 ParticleSeam *seams= 0; 01029 KDTree *tree=0; 01030 DerivedMesh *dm= NULL; 01031 float *jit= NULL; 01032 int i, seed, p=0, totthread= threads[0].tot; 01033 int cfrom=0; 01034 int totelem=0, totpart, *particle_element=0, children=0, totseam=0; 01035 int jitlevel= 1, distr; 01036 float *element_weight=NULL,*element_sum=NULL,*jitter_offset=NULL, *vweight=NULL; 01037 float cur, maxweight=0.0, tweight, totweight, inv_totweight, co[3], nor[3], orco[3], ornor[3]; 01038 01039 if(ELEM3(NULL, ob, psys, psys->part)) 01040 return 0; 01041 01042 part=psys->part; 01043 totpart=psys->totpart; 01044 if(totpart==0) 01045 return 0; 01046 01047 if (!finaldm->deformedOnly && !finaldm->getFaceDataArray(finaldm, CD_ORIGINDEX)) { 01048 printf("Can't create particles with the current modifier stack, disable destructive modifiers\n"); 01049 // XXX error("Can't paint with the current modifier stack, disable destructive modifiers"); 01050 return 0; 01051 } 01052 01053 /* First handle special cases */ 01054 if(from == PART_FROM_CHILD) { 01055 /* Simple children */ 01056 if(part->childtype != PART_CHILD_FACES) { 01057 BLI_srandom(31415926 + psys->seed + psys->child_seed); 01058 distribute_simple_children(scene, ob, finaldm, psys); 01059 return 0; 01060 } 01061 } 01062 else { 01063 /* Grid distribution */ 01064 if(part->distr==PART_DISTR_GRID && from != PART_FROM_VERT){ 01065 BLI_srandom(31415926 + psys->seed); 01066 dm= CDDM_from_mesh((Mesh*)ob->data, ob); 01067 distribute_grid(dm,psys); 01068 dm->release(dm); 01069 return 0; 01070 } 01071 } 01072 01073 /* Create trees and original coordinates if needed */ 01074 if(from == PART_FROM_CHILD) { 01075 distr=PART_DISTR_RAND; 01076 BLI_srandom(31415926 + psys->seed + psys->child_seed); 01077 dm= finaldm; 01078 children=1; 01079 01080 tree=BLI_kdtree_new(totpart); 01081 01082 for(p=0,pa=psys->particles; p<totpart; p++,pa++){ 01083 psys_particle_on_dm(dm,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco,ornor); 01084 transform_mesh_orco_verts((Mesh*)ob->data, &orco, 1, 1); 01085 BLI_kdtree_insert(tree, p, orco, ornor); 01086 } 01087 01088 BLI_kdtree_balance(tree); 01089 01090 totpart = get_psys_tot_child(scene, psys); 01091 cfrom = from = PART_FROM_FACE; 01092 } 01093 else { 01094 distr = part->distr; 01095 BLI_srandom(31415926 + psys->seed); 01096 01097 dm= CDDM_from_mesh((Mesh*)ob->data, ob); 01098 01099 /* we need orco for consistent distributions */ 01100 DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, get_mesh_orco_verts(ob)); 01101 01102 if(from == PART_FROM_VERT) { 01103 MVert *mv= dm->getVertDataArray(dm, CD_MVERT); 01104 float (*orcodata)[3]= dm->getVertDataArray(dm, CD_ORCO); 01105 int totvert = dm->getNumVerts(dm); 01106 01107 tree=BLI_kdtree_new(totvert); 01108 01109 for(p=0; p<totvert; p++) { 01110 if(orcodata) { 01111 VECCOPY(co,orcodata[p]) 01112 transform_mesh_orco_verts((Mesh*)ob->data, &co, 1, 1); 01113 } 01114 else 01115 VECCOPY(co,mv[p].co) 01116 BLI_kdtree_insert(tree,p,co,NULL); 01117 } 01118 01119 BLI_kdtree_balance(tree); 01120 } 01121 } 01122 01123 /* Get total number of emission elements and allocate needed arrays */ 01124 totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumFaces(dm); 01125 01126 if(totelem == 0){ 01127 distribute_invalid(scene, psys, children ? PART_FROM_CHILD : 0); 01128 01129 if(G.f & G_DEBUG) 01130 fprintf(stderr,"Particle distribution error: Nothing to emit from!\n"); 01131 01132 if(dm != finaldm) dm->release(dm); 01133 return 0; 01134 } 01135 01136 element_weight = MEM_callocN(sizeof(float)*totelem, "particle_distribution_weights"); 01137 particle_element= MEM_callocN(sizeof(int)*totpart, "particle_distribution_indexes"); 01138 element_sum = MEM_callocN(sizeof(float)*(totelem+1), "particle_distribution_sum"); 01139 jitter_offset = MEM_callocN(sizeof(float)*totelem, "particle_distribution_jitoff"); 01140 01141 /* Calculate weights from face areas */ 01142 if((part->flag&PART_EDISTR || children) && from != PART_FROM_VERT){ 01143 MVert *v1, *v2, *v3, *v4; 01144 float totarea=0.f, co1[3], co2[3], co3[3], co4[3]; 01145 float (*orcodata)[3]; 01146 01147 orcodata= dm->getVertDataArray(dm, CD_ORCO); 01148 01149 for(i=0; i<totelem; i++){ 01150 MFace *mf=dm->getFaceData(dm,i,CD_MFACE); 01151 01152 if(orcodata) { 01153 VECCOPY(co1, orcodata[mf->v1]); 01154 VECCOPY(co2, orcodata[mf->v2]); 01155 VECCOPY(co3, orcodata[mf->v3]); 01156 transform_mesh_orco_verts((Mesh*)ob->data, &co1, 1, 1); 01157 transform_mesh_orco_verts((Mesh*)ob->data, &co2, 1, 1); 01158 transform_mesh_orco_verts((Mesh*)ob->data, &co3, 1, 1); 01159 if(mf->v4) { 01160 VECCOPY(co4, orcodata[mf->v4]); 01161 transform_mesh_orco_verts((Mesh*)ob->data, &co4, 1, 1); 01162 } 01163 } 01164 else { 01165 v1= (MVert*)dm->getVertData(dm,mf->v1,CD_MVERT); 01166 v2= (MVert*)dm->getVertData(dm,mf->v2,CD_MVERT); 01167 v3= (MVert*)dm->getVertData(dm,mf->v3,CD_MVERT); 01168 VECCOPY(co1, v1->co); 01169 VECCOPY(co2, v2->co); 01170 VECCOPY(co3, v3->co); 01171 if(mf->v4) { 01172 v4= (MVert*)dm->getVertData(dm,mf->v4,CD_MVERT); 01173 VECCOPY(co4, v4->co); 01174 } 01175 } 01176 01177 cur = mf->v4 ? area_quad_v3(co1, co2, co3, co4) : area_tri_v3(co1, co2, co3); 01178 01179 if(cur > maxweight) 01180 maxweight = cur; 01181 01182 element_weight[i] = cur; 01183 totarea += cur; 01184 } 01185 01186 for(i=0; i<totelem; i++) 01187 element_weight[i] /= totarea; 01188 01189 maxweight /= totarea; 01190 } 01191 else{ 01192 float min=1.0f/(float)(MIN2(totelem,totpart)); 01193 for(i=0; i<totelem; i++) 01194 element_weight[i]=min; 01195 maxweight=min; 01196 } 01197 01198 /* Calculate weights from vgroup */ 01199 vweight = psys_cache_vgroup(dm,psys,PSYS_VG_DENSITY); 01200 01201 if(vweight){ 01202 if(from==PART_FROM_VERT) { 01203 for(i=0;i<totelem; i++) 01204 element_weight[i]*=vweight[i]; 01205 } 01206 else { /* PART_FROM_FACE / PART_FROM_VOLUME */ 01207 for(i=0;i<totelem; i++){ 01208 MFace *mf=dm->getFaceData(dm,i,CD_MFACE); 01209 tweight = vweight[mf->v1] + vweight[mf->v2] + vweight[mf->v3]; 01210 01211 if(mf->v4) { 01212 tweight += vweight[mf->v4]; 01213 tweight /= 4.0f; 01214 } 01215 else { 01216 tweight /= 3.0f; 01217 } 01218 01219 element_weight[i]*=tweight; 01220 } 01221 } 01222 MEM_freeN(vweight); 01223 } 01224 01225 /* Calculate total weight of all elements */ 01226 totweight= 0.0f; 01227 for(i=0;i<totelem; i++) 01228 totweight += element_weight[i]; 01229 01230 inv_totweight = (totweight > 0.f ? 1.f/totweight : 0.f); 01231 01232 /* Calculate cumulative weights */ 01233 element_sum[0]= 0.0f; 01234 for(i=0; i<totelem; i++) 01235 element_sum[i+1]= element_sum[i] + element_weight[i] * inv_totweight; 01236 01237 /* Finally assign elements to particles */ 01238 if((part->flag&PART_TRAND) || (part->simplify_flag&PART_SIMPLIFY_ENABLE)) { 01239 float pos; 01240 01241 for(p=0; p<totpart; p++) { 01242 /* In theory element_sum[totelem] should be 1.0, but due to float errors this is not necessarily always true, so scale pos accordingly. */ 01243 pos= BLI_frand() * element_sum[totelem]; 01244 particle_element[p]= distribute_binary_search(element_sum, totelem, pos); 01245 particle_element[p]= MIN2(totelem-1, particle_element[p]); 01246 jitter_offset[particle_element[p]]= pos; 01247 } 01248 } 01249 else { 01250 double step, pos; 01251 01252 step= (totpart < 2) ? 0.5 : 1.0/(double)totpart; 01253 pos= 1e-6; /* tiny offset to avoid zero weight face */ 01254 i= 0; 01255 01256 for(p=0; p<totpart; p++, pos+=step) { 01257 while((i < totelem) && (pos > element_sum[i+1])) 01258 i++; 01259 01260 particle_element[p]= MIN2(totelem-1, i); 01261 01262 /* avoid zero weight face */ 01263 if(p == totpart-1 && element_weight[particle_element[p]] == 0.0f) 01264 particle_element[p]= particle_element[p-1]; 01265 01266 jitter_offset[particle_element[p]]= pos; 01267 } 01268 } 01269 01270 MEM_freeN(element_sum); 01271 01272 /* For hair, sort by origindex (allows optimizations in rendering), */ 01273 /* however with virtual parents the children need to be in random order. */ 01274 if(part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents!=0.0f)) { 01275 COMPARE_ORIG_INDEX = NULL; 01276 01277 if(from == PART_FROM_VERT) { 01278 if(dm->numVertData) 01279 COMPARE_ORIG_INDEX= dm->getVertDataArray(dm, CD_ORIGINDEX); 01280 } 01281 else { 01282 if(dm->numFaceData) 01283 COMPARE_ORIG_INDEX= dm->getFaceDataArray(dm, CD_ORIGINDEX); 01284 } 01285 01286 if(COMPARE_ORIG_INDEX) { 01287 qsort(particle_element, totpart, sizeof(int), distribute_compare_orig_index); 01288 COMPARE_ORIG_INDEX = NULL; 01289 } 01290 } 01291 01292 /* Create jittering if needed */ 01293 if(distr==PART_DISTR_JIT && ELEM(from,PART_FROM_FACE,PART_FROM_VOLUME)) { 01294 jitlevel= part->userjit; 01295 01296 if(jitlevel == 0) { 01297 jitlevel= totpart/totelem; 01298 if(part->flag & PART_EDISTR) jitlevel*= 2; /* looks better in general, not very scietific */ 01299 if(jitlevel<3) jitlevel= 3; 01300 } 01301 01302 jit= MEM_callocN((2+ jitlevel*2)*sizeof(float), "jit"); 01303 01304 /* for small amounts of particles we use regular jitter since it looks 01305 * a bit better, for larger amounts we switch to hammersley sequence 01306 * because it is much faster */ 01307 if(jitlevel < 25) 01308 init_mv_jit(jit, jitlevel, psys->seed, part->jitfac); 01309 else 01310 hammersley_create(jit, jitlevel+1, psys->seed, part->jitfac); 01311 BLI_array_randomize(jit, 2*sizeof(float), jitlevel, psys->seed); /* for custom jit or even distribution */ 01312 } 01313 01314 /* Setup things for threaded distribution */ 01315 ctx->tree= tree; 01316 ctx->seams= seams; 01317 ctx->totseam= totseam; 01318 ctx->sim.psys= psys; 01319 ctx->index= particle_element; 01320 ctx->jit= jit; 01321 ctx->jitlevel= jitlevel; 01322 ctx->jitoff= jitter_offset; 01323 ctx->weight= element_weight; 01324 ctx->maxweight= maxweight; 01325 ctx->from= (children)? PART_FROM_CHILD: from; 01326 ctx->cfrom= cfrom; 01327 ctx->distr= distr; 01328 ctx->dm= dm; 01329 ctx->tpars= tpars; 01330 01331 if(children) { 01332 totpart= psys_render_simplify_distribution(ctx, totpart); 01333 alloc_child_particles(psys, totpart); 01334 } 01335 01336 if(!children || psys->totchild < 10000) 01337 totthread= 1; 01338 01339 seed= 31415926 + ctx->sim.psys->seed; 01340 for(i=0; i<totthread; i++) { 01341 threads[i].rng= rng_new(seed); 01342 threads[i].tot= totthread; 01343 } 01344 01345 return 1; 01346 } 01347 01348 static void distribute_particles_on_dm(ParticleSimulationData *sim, int from) 01349 { 01350 DerivedMesh *finaldm = sim->psmd->dm; 01351 ListBase threads; 01352 ParticleThread *pthreads; 01353 ParticleThreadContext *ctx; 01354 int i, totthread; 01355 01356 pthreads= psys_threads_create(sim); 01357 01358 if(!distribute_threads_init_data(pthreads, sim->scene, finaldm, from)) { 01359 psys_threads_free(pthreads); 01360 return; 01361 } 01362 01363 totthread= pthreads[0].tot; 01364 if(totthread > 1) { 01365 BLI_init_threads(&threads, distribute_threads_exec_cb, totthread); 01366 01367 for(i=0; i<totthread; i++) 01368 BLI_insert_thread(&threads, &pthreads[i]); 01369 01370 BLI_end_threads(&threads); 01371 } 01372 else 01373 distribute_threads_exec_cb(&pthreads[0]); 01374 01375 psys_calc_dmcache(sim->ob, finaldm, sim->psys); 01376 01377 ctx= pthreads[0].ctx; 01378 if(ctx->dm != finaldm) 01379 ctx->dm->release(ctx->dm); 01380 01381 psys_threads_free(pthreads); 01382 } 01383 01384 /* ready for future use, to emit particles without geometry */ 01385 static void distribute_particles_on_shape(ParticleSimulationData *sim, int UNUSED(from)) 01386 { 01387 distribute_invalid(sim->scene, sim->psys, 0); 01388 01389 fprintf(stderr,"Shape emission not yet possible!\n"); 01390 } 01391 01392 static void distribute_particles(ParticleSimulationData *sim, int from) 01393 { 01394 PARTICLE_PSMD; 01395 int distr_error=0; 01396 01397 if(psmd){ 01398 if(psmd->dm) 01399 distribute_particles_on_dm(sim, from); 01400 else 01401 distr_error=1; 01402 } 01403 else 01404 distribute_particles_on_shape(sim, from); 01405 01406 if(distr_error){ 01407 distribute_invalid(sim->scene, sim->psys, from); 01408 01409 fprintf(stderr,"Particle distribution error!\n"); 01410 } 01411 } 01412 01413 /* threaded child particle distribution and path caching */ 01414 ParticleThread *psys_threads_create(ParticleSimulationData *sim) 01415 { 01416 ParticleThread *threads; 01417 ParticleThreadContext *ctx; 01418 int i, totthread; 01419 01420 if(sim->scene->r.mode & R_FIXED_THREADS) 01421 totthread= sim->scene->r.threads; 01422 else 01423 totthread= BLI_system_thread_count(); 01424 01425 threads= MEM_callocN(sizeof(ParticleThread)*totthread, "ParticleThread"); 01426 ctx= MEM_callocN(sizeof(ParticleThreadContext), "ParticleThreadContext"); 01427 01428 ctx->sim = *sim; 01429 ctx->dm= ctx->sim.psmd->dm; 01430 ctx->ma= give_current_material(sim->ob, sim->psys->part->omat); 01431 01432 memset(threads, 0, sizeof(ParticleThread)*totthread); 01433 01434 for(i=0; i<totthread; i++) { 01435 threads[i].ctx= ctx; 01436 threads[i].num= i; 01437 threads[i].tot= totthread; 01438 } 01439 01440 return threads; 01441 } 01442 01443 void psys_threads_free(ParticleThread *threads) 01444 { 01445 ParticleThreadContext *ctx= threads[0].ctx; 01446 int i, totthread= threads[0].tot; 01447 01448 /* path caching */ 01449 if(ctx->vg_length) 01450 MEM_freeN(ctx->vg_length); 01451 if(ctx->vg_clump) 01452 MEM_freeN(ctx->vg_clump); 01453 if(ctx->vg_kink) 01454 MEM_freeN(ctx->vg_kink); 01455 if(ctx->vg_rough1) 01456 MEM_freeN(ctx->vg_rough1); 01457 if(ctx->vg_rough2) 01458 MEM_freeN(ctx->vg_rough2); 01459 if(ctx->vg_roughe) 01460 MEM_freeN(ctx->vg_roughe); 01461 01462 if(ctx->sim.psys->lattice){ 01463 end_latt_deform(ctx->sim.psys->lattice); 01464 ctx->sim.psys->lattice= NULL; 01465 } 01466 01467 /* distribution */ 01468 if(ctx->jit) MEM_freeN(ctx->jit); 01469 if(ctx->jitoff) MEM_freeN(ctx->jitoff); 01470 if(ctx->weight) MEM_freeN(ctx->weight); 01471 if(ctx->index) MEM_freeN(ctx->index); 01472 if(ctx->skip) MEM_freeN(ctx->skip); 01473 if(ctx->seams) MEM_freeN(ctx->seams); 01474 //if(ctx->vertpart) MEM_freeN(ctx->vertpart); 01475 BLI_kdtree_free(ctx->tree); 01476 01477 /* threads */ 01478 for(i=0; i<totthread; i++) { 01479 if(threads[i].rng) 01480 rng_free(threads[i].rng); 01481 if(threads[i].rng_path) 01482 rng_free(threads[i].rng_path); 01483 } 01484 01485 MEM_freeN(ctx); 01486 MEM_freeN(threads); 01487 } 01488 01489 /* set particle parameters that don't change during particle's life */ 01490 void initialize_particle(ParticleSimulationData *sim, ParticleData *pa, int p) 01491 { 01492 ParticleSystem *psys = sim->psys; 01493 ParticleSettings *part = psys->part; 01494 ParticleTexture ptex; 01495 01496 pa->flag &= ~PARS_UNEXIST; 01497 01498 if(part->type != PART_FLUID) { 01499 psys_get_texture(sim, pa, &ptex, PAMAP_INIT, 0.f); 01500 01501 if(ptex.exist < PSYS_FRAND(p+125)) 01502 pa->flag |= PARS_UNEXIST; 01503 01504 pa->time = (part->type == PART_HAIR) ? 0.f : part->sta + (part->end - part->sta)*ptex.time; 01505 } 01506 01507 pa->hair_index = 0; 01508 /* we can't reset to -1 anymore since we've figured out correct index in distribute_particles */ 01509 /* usage other than straight after distribute has to handle this index by itself - jahka*/ 01510 //pa->num_dmcache = DMCACHE_NOTFOUND; /* assume we dont have a derived mesh face */ 01511 } 01512 static void initialize_all_particles(ParticleSimulationData *sim) 01513 { 01514 ParticleSystem *psys = sim->psys; 01515 PARTICLE_P; 01516 01517 psys->totunexist = 0; 01518 01519 LOOP_PARTICLES { 01520 if((pa->flag & PARS_UNEXIST)==0) 01521 initialize_particle(sim, pa, p); 01522 01523 if(pa->flag & PARS_UNEXIST) 01524 psys->totunexist++; 01525 } 01526 01527 /* Free unexisting particles. */ 01528 if(psys->totpart && psys->totunexist == psys->totpart) { 01529 if(psys->particles->boid) 01530 MEM_freeN(psys->particles->boid); 01531 01532 MEM_freeN(psys->particles); 01533 psys->particles = NULL; 01534 psys->totpart = psys->totunexist = 0; 01535 } 01536 01537 if(psys->totunexist) { 01538 int newtotpart = psys->totpart - psys->totunexist; 01539 ParticleData *npa, *newpars; 01540 01541 npa = newpars = MEM_callocN(newtotpart * sizeof(ParticleData), "particles"); 01542 01543 for(p=0, pa=psys->particles; p<newtotpart; p++, pa++, npa++) { 01544 while(pa->flag & PARS_UNEXIST) 01545 pa++; 01546 01547 memcpy(npa, pa, sizeof(ParticleData)); 01548 } 01549 01550 if(psys->particles->boid) 01551 MEM_freeN(psys->particles->boid); 01552 MEM_freeN(psys->particles); 01553 psys->particles = newpars; 01554 psys->totpart -= psys->totunexist; 01555 01556 if(psys->particles->boid) { 01557 BoidParticle *newboids = MEM_callocN(psys->totpart * sizeof(BoidParticle), "boid particles"); 01558 01559 LOOP_PARTICLES 01560 pa->boid = newboids++; 01561 01562 } 01563 } 01564 } 01565 void psys_get_birth_coordinates(ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, float dtime, float cfra) 01566 { 01567 Object *ob = sim->ob; 01568 ParticleSystem *psys = sim->psys; 01569 ParticleSettings *part; 01570 ParticleTexture ptex; 01571 float fac, phasefac, nor[3]={0,0,0},loc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4]; 01572 float r_vel[3],r_ave[3],r_rot[4],vec[3],p_vel[3]={0.0,0.0,0.0}; 01573 float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0}; 01574 float q_phase[4]; 01575 int p = pa - psys->particles; 01576 part=psys->part; 01577 01578 /* get birth location from object */ 01579 if(part->tanfac != 0.f) 01580 psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0); 01581 else 01582 psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0); 01583 01584 /* get possible textural influence */ 01585 psys_get_texture(sim, pa, &ptex, PAMAP_IVEL, cfra); 01586 01587 /* particles live in global space so */ 01588 /* let's convert: */ 01589 /* -location */ 01590 mul_m4_v3(ob->obmat, loc); 01591 01592 /* -normal */ 01593 mul_mat3_m4_v3(ob->obmat, nor); 01594 normalize_v3(nor); 01595 01596 /* -tangent */ 01597 if(part->tanfac!=0.0f){ 01598 //float phase=vg_rot?2.0f*(psys_particle_value_from_verts(sim->psmd->dm,part->from,pa,vg_rot)-0.5f):0.0f; 01599 float phase=0.0f; 01600 mul_v3_fl(vtan,-(float)cos((float)M_PI*(part->tanphase+phase))); 01601 fac=-(float)sin((float)M_PI*(part->tanphase+phase)); 01602 VECADDFAC(vtan,vtan,utan,fac); 01603 01604 mul_mat3_m4_v3(ob->obmat,vtan); 01605 01606 VECCOPY(utan,nor); 01607 mul_v3_fl(utan,dot_v3v3(vtan,nor)); 01608 VECSUB(vtan,vtan,utan); 01609 01610 normalize_v3(vtan); 01611 } 01612 01613 01614 /* -velocity */ 01615 if(part->randfac != 0.0f){ 01616 r_vel[0] = 2.0f * (PSYS_FRAND(p + 10) - 0.5f); 01617 r_vel[1] = 2.0f * (PSYS_FRAND(p + 11) - 0.5f); 01618 r_vel[2] = 2.0f * (PSYS_FRAND(p + 12) - 0.5f); 01619 01620 mul_mat3_m4_v3(ob->obmat, r_vel); 01621 normalize_v3(r_vel); 01622 } 01623 01624 /* -angular velocity */ 01625 if(part->avemode==PART_AVE_RAND){ 01626 r_ave[0] = 2.0f * (PSYS_FRAND(p + 13) - 0.5f); 01627 r_ave[1] = 2.0f * (PSYS_FRAND(p + 14) - 0.5f); 01628 r_ave[2] = 2.0f * (PSYS_FRAND(p + 15) - 0.5f); 01629 01630 mul_mat3_m4_v3(ob->obmat,r_ave); 01631 normalize_v3(r_ave); 01632 } 01633 01634 /* -rotation */ 01635 if(part->randrotfac != 0.0f){ 01636 r_rot[0] = 2.0f * (PSYS_FRAND(p + 16) - 0.5f); 01637 r_rot[1] = 2.0f * (PSYS_FRAND(p + 17) - 0.5f); 01638 r_rot[2] = 2.0f * (PSYS_FRAND(p + 18) - 0.5f); 01639 r_rot[3] = 2.0f * (PSYS_FRAND(p + 19) - 0.5f); 01640 normalize_qt(r_rot); 01641 01642 mat4_to_quat(rot,ob->obmat); 01643 mul_qt_qtqt(r_rot,r_rot,rot); 01644 } 01645 01646 if(part->phystype==PART_PHYS_BOIDS && pa->boid) { 01647 float dvec[3], q[4], mat[3][3]; 01648 01649 copy_v3_v3(state->co,loc); 01650 01651 /* boids don't get any initial velocity */ 01652 zero_v3(state->vel); 01653 01654 /* boids store direction in ave */ 01655 if(fabsf(nor[2])==1.0f) { 01656 sub_v3_v3v3(state->ave, loc, ob->obmat[3]); 01657 normalize_v3(state->ave); 01658 } 01659 else { 01660 VECCOPY(state->ave, nor); 01661 } 01662 01663 /* calculate rotation matrix */ 01664 project_v3_v3v3(dvec, r_vel, state->ave); 01665 sub_v3_v3v3(mat[0], state->ave, dvec); 01666 normalize_v3(mat[0]); 01667 negate_v3_v3(mat[2], r_vel); 01668 normalize_v3(mat[2]); 01669 cross_v3_v3v3(mat[1], mat[2], mat[0]); 01670 01671 /* apply rotation */ 01672 mat3_to_quat_is_ok( q,mat); 01673 copy_qt_qt(state->rot, q); 01674 } 01675 else { 01676 /* conversion done so now we apply new: */ 01677 /* -velocity from: */ 01678 01679 /* *reactions */ 01680 if(dtime > 0.f){ 01681 sub_v3_v3v3(vel, pa->state.vel, pa->prev_state.vel); 01682 } 01683 01684 /* *emitter velocity */ 01685 if(dtime != 0.f && part->obfac != 0.f){ 01686 sub_v3_v3v3(vel, loc, state->co); 01687 mul_v3_fl(vel, part->obfac/dtime); 01688 } 01689 01690 /* *emitter normal */ 01691 if(part->normfac != 0.f) 01692 madd_v3_v3fl(vel, nor, part->normfac); 01693 01694 /* *emitter tangent */ 01695 if(sim->psmd && part->tanfac != 0.f) 01696 madd_v3_v3fl(vel, vtan, part->tanfac); 01697 01698 /* *emitter object orientation */ 01699 if(part->ob_vel[0] != 0.f) { 01700 normalize_v3_v3(vec, ob->obmat[0]); 01701 madd_v3_v3fl(vel, vec, part->ob_vel[0]); 01702 } 01703 if(part->ob_vel[1] != 0.f) { 01704 normalize_v3_v3(vec, ob->obmat[1]); 01705 madd_v3_v3fl(vel, vec, part->ob_vel[1]); 01706 } 01707 if(part->ob_vel[2] != 0.f) { 01708 normalize_v3_v3(vec, ob->obmat[2]); 01709 madd_v3_v3fl(vel, vec, part->ob_vel[2]); 01710 } 01711 01712 /* *texture */ 01713 /* TODO */ 01714 01715 /* *random */ 01716 if(part->randfac != 0.f) 01717 madd_v3_v3fl(vel, r_vel, part->randfac); 01718 01719 /* *particle */ 01720 if(part->partfac != 0.f) 01721 madd_v3_v3fl(vel, p_vel, part->partfac); 01722 01723 mul_v3_v3fl(state->vel, vel, ptex.ivel); 01724 01725 /* -location from emitter */ 01726 copy_v3_v3(state->co,loc); 01727 01728 /* -rotation */ 01729 unit_qt(state->rot); 01730 01731 if(part->rotmode){ 01732 /* create vector into which rotation is aligned */ 01733 switch(part->rotmode){ 01734 case PART_ROT_NOR: 01735 copy_v3_v3(rot_vec, nor); 01736 break; 01737 case PART_ROT_VEL: 01738 copy_v3_v3(rot_vec, vel); 01739 break; 01740 case PART_ROT_GLOB_X: 01741 case PART_ROT_GLOB_Y: 01742 case PART_ROT_GLOB_Z: 01743 rot_vec[part->rotmode - PART_ROT_GLOB_X] = 1.0f; 01744 break; 01745 case PART_ROT_OB_X: 01746 case PART_ROT_OB_Y: 01747 case PART_ROT_OB_Z: 01748 copy_v3_v3(rot_vec, ob->obmat[part->rotmode - PART_ROT_OB_X]); 01749 break; 01750 } 01751 01752 /* create rotation quat */ 01753 negate_v3(rot_vec); 01754 vec_to_quat( q2,rot_vec, OB_POSX, OB_POSZ); 01755 01756 /* randomize rotation quat */ 01757 if(part->randrotfac!=0.0f) 01758 interp_qt_qtqt(rot, q2, r_rot, part->randrotfac); 01759 else 01760 copy_qt_qt(rot,q2); 01761 01762 /* rotation phase */ 01763 phasefac = part->phasefac; 01764 if(part->randphasefac != 0.0f) 01765 phasefac += part->randphasefac * PSYS_FRAND(p + 20); 01766 axis_angle_to_quat( q_phase,x_vec, phasefac*(float)M_PI); 01767 01768 /* combine base rotation & phase */ 01769 mul_qt_qtqt(state->rot, rot, q_phase); 01770 } 01771 01772 /* -angular velocity */ 01773 01774 zero_v3(state->ave); 01775 01776 if(part->avemode){ 01777 switch(part->avemode){ 01778 case PART_AVE_SPIN: 01779 copy_v3_v3(state->ave, vel); 01780 break; 01781 case PART_AVE_RAND: 01782 copy_v3_v3(state->ave, r_ave); 01783 break; 01784 } 01785 normalize_v3(state->ave); 01786 mul_v3_fl(state->ave, part->avefac); 01787 } 01788 } 01789 } 01790 /* sets particle to the emitter surface with initial velocity & rotation */ 01791 void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, float cfra) 01792 { 01793 Object *ob = sim->ob; 01794 ParticleSystem *psys = sim->psys; 01795 ParticleSettings *part; 01796 ParticleTexture ptex; 01797 int p = pa - psys->particles; 01798 part=psys->part; 01799 01800 /* get precise emitter matrix if particle is born */ 01801 if(part->type!=PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) { 01802 /* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */ 01803 while(ob) { 01804 BKE_animsys_evaluate_animdata(&ob->id, ob->adt, pa->time, ADT_RECALC_ANIM); 01805 ob = ob->parent; 01806 } 01807 ob = sim->ob; 01808 where_is_object_time(sim->scene, ob, pa->time); 01809 } 01810 01811 psys_get_birth_coordinates(sim, pa, &pa->state, dtime, cfra); 01812 01813 if(part->phystype==PART_PHYS_BOIDS && pa->boid) { 01814 BoidParticle *bpa = pa->boid; 01815 01816 /* and gravity in r_ve */ 01817 bpa->gravity[0] = bpa->gravity[1] = 0.0f; 01818 bpa->gravity[2] = -1.0f; 01819 if((sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) 01820 && sim->scene->physics_settings.gravity[2]!=0.0f) 01821 bpa->gravity[2] = sim->scene->physics_settings.gravity[2]; 01822 01823 bpa->data.health = part->boids->health; 01824 bpa->data.mode = eBoidMode_InAir; 01825 bpa->data.state_id = ((BoidState*)part->boids->states.first)->id; 01826 bpa->data.acc[0]=bpa->data.acc[1]=bpa->data.acc[2]=0.0f; 01827 } 01828 01829 01830 if(part->type == PART_HAIR){ 01831 pa->lifetime = 100.0f; 01832 } 01833 else{ 01834 /* get possible textural influence */ 01835 psys_get_texture(sim, pa, &ptex, PAMAP_LIFE, cfra); 01836 01837 pa->lifetime = part->lifetime * ptex.life; 01838 01839 if(part->randlife != 0.0f) 01840 pa->lifetime *= 1.0f - part->randlife * PSYS_FRAND(p + 21); 01841 } 01842 01843 pa->dietime = pa->time + pa->lifetime; 01844 01845 if(sim->psys->pointcache && sim->psys->pointcache->flag & PTCACHE_BAKED && 01846 sim->psys->pointcache->mem_cache.first) { 01847 float dietime = psys_get_dietime_from_cache(sim->psys->pointcache, p); 01848 pa->dietime = MIN2(pa->dietime, dietime); 01849 } 01850 01851 if(pa->time > cfra) 01852 pa->alive = PARS_UNBORN; 01853 else if(pa->dietime <= cfra) 01854 pa->alive = PARS_DEAD; 01855 else 01856 pa->alive = PARS_ALIVE; 01857 01858 pa->state.time = cfra; 01859 } 01860 static void reset_all_particles(ParticleSimulationData *sim, float dtime, float cfra, int from) 01861 { 01862 ParticleData *pa; 01863 int p, totpart=sim->psys->totpart; 01864 01865 for(p=from, pa=sim->psys->particles+from; p<totpart; p++, pa++) 01866 reset_particle(sim, pa, dtime, cfra); 01867 } 01868 /************************************************/ 01869 /* Particle targets */ 01870 /************************************************/ 01871 ParticleSystem *psys_get_target_system(Object *ob, ParticleTarget *pt) 01872 { 01873 ParticleSystem *psys = NULL; 01874 01875 if(pt->ob == NULL || pt->ob == ob) 01876 psys = BLI_findlink(&ob->particlesystem, pt->psys-1); 01877 else 01878 psys = BLI_findlink(&pt->ob->particlesystem, pt->psys-1); 01879 01880 if(psys) 01881 pt->flag |= PTARGET_VALID; 01882 else 01883 pt->flag &= ~PTARGET_VALID; 01884 01885 return psys; 01886 } 01887 /************************************************/ 01888 /* Keyed particles */ 01889 /************************************************/ 01890 /* Counts valid keyed targets */ 01891 void psys_count_keyed_targets(ParticleSimulationData *sim) 01892 { 01893 ParticleSystem *psys = sim->psys, *kpsys; 01894 ParticleTarget *pt = psys->targets.first; 01895 int keys_valid = 1; 01896 psys->totkeyed = 0; 01897 01898 for(; pt; pt=pt->next) { 01899 kpsys = psys_get_target_system(sim->ob, pt); 01900 01901 if(kpsys && kpsys->totpart) { 01902 psys->totkeyed += keys_valid; 01903 if(psys->flag & PSYS_KEYED_TIMING && pt->duration != 0.0f) 01904 psys->totkeyed += 1; 01905 } 01906 else { 01907 keys_valid = 0; 01908 } 01909 } 01910 01911 psys->totkeyed *= psys->flag & PSYS_KEYED_TIMING ? 1 : psys->part->keyed_loops; 01912 } 01913 01914 static void set_keyed_keys(ParticleSimulationData *sim) 01915 { 01916 ParticleSystem *psys = sim->psys; 01917 ParticleSimulationData ksim= {0}; 01918 ParticleTarget *pt; 01919 PARTICLE_P; 01920 ParticleKey *key; 01921 int totpart = psys->totpart, k, totkeys = psys->totkeyed; 01922 int keyed_flag = 0; 01923 01924 ksim.scene= sim->scene; 01925 01926 /* no proper targets so let's clear and bail out */ 01927 if(psys->totkeyed==0) { 01928 free_keyed_keys(psys); 01929 psys->flag &= ~PSYS_KEYED; 01930 return; 01931 } 01932 01933 if(totpart && psys->particles->totkey != totkeys) { 01934 free_keyed_keys(psys); 01935 01936 key = MEM_callocN(totpart*totkeys*sizeof(ParticleKey), "Keyed keys"); 01937 01938 LOOP_PARTICLES { 01939 pa->keys = key; 01940 pa->totkey = totkeys; 01941 key += totkeys; 01942 } 01943 } 01944 01945 psys->flag &= ~PSYS_KEYED; 01946 01947 01948 pt = psys->targets.first; 01949 for(k=0; k<totkeys; k++) { 01950 ksim.ob = pt->ob ? pt->ob : sim->ob; 01951 ksim.psys = BLI_findlink(&ksim.ob->particlesystem, pt->psys - 1); 01952 keyed_flag = (ksim.psys->flag & PSYS_KEYED); 01953 ksim.psys->flag &= ~PSYS_KEYED; 01954 01955 LOOP_PARTICLES { 01956 key = pa->keys + k; 01957 key->time = -1.0; /* use current time */ 01958 01959 psys_get_particle_state(&ksim, p%ksim.psys->totpart, key, 1); 01960 01961 if(psys->flag & PSYS_KEYED_TIMING){ 01962 key->time = pa->time + pt->time; 01963 if(pt->duration != 0.0f && k+1 < totkeys) { 01964 copy_particle_key(key+1, key, 1); 01965 (key+1)->time = pa->time + pt->time + pt->duration; 01966 } 01967 } 01968 else if(totkeys > 1) 01969 key->time = pa->time + (float)k / (float)(totkeys - 1) * pa->lifetime; 01970 else 01971 key->time = pa->time; 01972 } 01973 01974 if(psys->flag & PSYS_KEYED_TIMING && pt->duration!=0.0f) 01975 k++; 01976 01977 ksim.psys->flag |= keyed_flag; 01978 01979 pt = (pt->next && pt->next->flag & PTARGET_VALID)? pt->next : psys->targets.first; 01980 } 01981 01982 psys->flag |= PSYS_KEYED; 01983 } 01984 01985 /************************************************/ 01986 /* Point Cache */ 01987 /************************************************/ 01988 void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys) 01989 { 01990 PointCache *cache = psys->pointcache; 01991 01992 if(cache->flag & PTCACHE_DISK_CACHE && cache->mem_cache.first == NULL) { 01993 PTCacheID pid; 01994 BKE_ptcache_id_from_particles(&pid, ob, psys); 01995 cache->flag &= ~PTCACHE_DISK_CACHE; 01996 BKE_ptcache_disk_to_mem(&pid); 01997 cache->flag |= PTCACHE_DISK_CACHE; 01998 } 01999 } 02000 static void psys_clear_temp_pointcache(ParticleSystem *psys) 02001 { 02002 if(psys->pointcache->flag & PTCACHE_DISK_CACHE) 02003 BKE_ptcache_free_mem(&psys->pointcache->mem_cache); 02004 } 02005 void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra, int *efra) 02006 { 02007 ParticleSettings *part = psys->part; 02008 02009 *sfra = MAX2(1, (int)part->sta); 02010 *efra = MIN2((int)(part->end + part->lifetime + 1.0f), scene->r.efra); 02011 } 02012 02013 /************************************************/ 02014 /* Effectors */ 02015 /************************************************/ 02016 static void psys_update_particle_bvhtree(ParticleSystem *psys, float cfra) 02017 { 02018 if(psys) { 02019 PARTICLE_P; 02020 int totpart = 0; 02021 02022 if(!psys->bvhtree || psys->bvhtree_frame != cfra) { 02023 LOOP_SHOWN_PARTICLES { 02024 totpart++; 02025 } 02026 02027 BLI_bvhtree_free(psys->bvhtree); 02028 psys->bvhtree = BLI_bvhtree_new(totpart, 0.0, 4, 6); 02029 02030 LOOP_SHOWN_PARTICLES { 02031 if(pa->alive == PARS_ALIVE) { 02032 if(pa->state.time == cfra) 02033 BLI_bvhtree_insert(psys->bvhtree, p, pa->prev_state.co, 1); 02034 else 02035 BLI_bvhtree_insert(psys->bvhtree, p, pa->state.co, 1); 02036 } 02037 } 02038 BLI_bvhtree_balance(psys->bvhtree); 02039 02040 psys->bvhtree_frame = cfra; 02041 } 02042 } 02043 } 02044 void psys_update_particle_tree(ParticleSystem *psys, float cfra) 02045 { 02046 if(psys) { 02047 PARTICLE_P; 02048 int totpart = 0; 02049 02050 if(!psys->tree || psys->tree_frame != cfra) { 02051 LOOP_SHOWN_PARTICLES { 02052 totpart++; 02053 } 02054 02055 BLI_kdtree_free(psys->tree); 02056 psys->tree = BLI_kdtree_new(psys->totpart); 02057 02058 LOOP_SHOWN_PARTICLES { 02059 if(pa->alive == PARS_ALIVE) { 02060 if(pa->state.time == cfra) 02061 BLI_kdtree_insert(psys->tree, p, pa->prev_state.co, NULL); 02062 else 02063 BLI_kdtree_insert(psys->tree, p, pa->state.co, NULL); 02064 } 02065 } 02066 BLI_kdtree_balance(psys->tree); 02067 02068 psys->tree_frame = cfra; 02069 } 02070 } 02071 } 02072 02073 static void psys_update_effectors(ParticleSimulationData *sim) 02074 { 02075 pdEndEffectors(&sim->psys->effectors); 02076 sim->psys->effectors = pdInitEffectors(sim->scene, sim->ob, sim->psys, sim->psys->part->effector_weights); 02077 precalc_guides(sim, sim->psys->effectors); 02078 } 02079 02080 static void integrate_particle(ParticleSettings *part, ParticleData *pa, float dtime, float *external_acceleration, void (*force_func)(void *forcedata, ParticleKey *state, float *force, float *impulse), void *forcedata) 02081 { 02082 ParticleKey states[5]; 02083 float force[3],acceleration[3],impulse[3],dx[4][3],dv[4][3],oldpos[3]; 02084 float pa_mass= (part->flag & PART_SIZEMASS ? part->mass * pa->size : part->mass); 02085 int i, steps=1; 02086 int integrator = part->integrator; 02087 02088 copy_v3_v3(oldpos, pa->state.co); 02089 02090 /* Verlet integration behaves strangely with moving emitters, so do first step with euler. */ 02091 if(pa->prev_state.time < 0.f && integrator == PART_INT_VERLET) 02092 integrator = PART_INT_EULER; 02093 02094 switch(integrator){ 02095 case PART_INT_EULER: 02096 steps=1; 02097 break; 02098 case PART_INT_MIDPOINT: 02099 steps=2; 02100 break; 02101 case PART_INT_RK4: 02102 steps=4; 02103 break; 02104 case PART_INT_VERLET: 02105 steps=1; 02106 break; 02107 } 02108 02109 copy_particle_key(states, &pa->state, 1); 02110 02111 states->time = 0.f; 02112 02113 for(i=0; i<steps; i++){ 02114 zero_v3(force); 02115 zero_v3(impulse); 02116 02117 force_func(forcedata, states+i, force, impulse); 02118 02119 /* force to acceleration*/ 02120 mul_v3_v3fl(acceleration, force, 1.0f/pa_mass); 02121 02122 if(external_acceleration) 02123 add_v3_v3(acceleration, external_acceleration); 02124 02125 /* calculate next state */ 02126 add_v3_v3(states[i].vel, impulse); 02127 02128 switch(integrator){ 02129 case PART_INT_EULER: 02130 madd_v3_v3v3fl(pa->state.co, states->co, states->vel, dtime); 02131 madd_v3_v3v3fl(pa->state.vel, states->vel, acceleration, dtime); 02132 break; 02133 case PART_INT_MIDPOINT: 02134 if(i==0){ 02135 madd_v3_v3v3fl(states[1].co, states->co, states->vel, dtime*0.5f); 02136 madd_v3_v3v3fl(states[1].vel, states->vel, acceleration, dtime*0.5f); 02137 states[1].time = dtime*0.5f; 02138 /*fra=sim->psys->cfra+0.5f*dfra;*/ 02139 } 02140 else{ 02141 madd_v3_v3v3fl(pa->state.co, states->co, states[1].vel, dtime); 02142 madd_v3_v3v3fl(pa->state.vel, states->vel, acceleration, dtime); 02143 } 02144 break; 02145 case PART_INT_RK4: 02146 switch(i){ 02147 case 0: 02148 copy_v3_v3(dx[0], states->vel); 02149 mul_v3_fl(dx[0], dtime); 02150 copy_v3_v3(dv[0], acceleration); 02151 mul_v3_fl(dv[0], dtime); 02152 02153 madd_v3_v3v3fl(states[1].co, states->co, dx[0], 0.5f); 02154 madd_v3_v3v3fl(states[1].vel, states->vel, dv[0], 0.5f); 02155 states[1].time = dtime*0.5f; 02156 /*fra=sim->psys->cfra+0.5f*dfra;*/ 02157 break; 02158 case 1: 02159 madd_v3_v3v3fl(dx[1], states->vel, dv[0], 0.5f); 02160 mul_v3_fl(dx[1], dtime); 02161 copy_v3_v3(dv[1], acceleration); 02162 mul_v3_fl(dv[1], dtime); 02163 02164 madd_v3_v3v3fl(states[2].co, states->co, dx[1], 0.5f); 02165 madd_v3_v3v3fl(states[2].vel, states->vel, dv[1], 0.5f); 02166 states[2].time = dtime*0.5f; 02167 break; 02168 case 2: 02169 madd_v3_v3v3fl(dx[2], states->vel, dv[1], 0.5f); 02170 mul_v3_fl(dx[2], dtime); 02171 copy_v3_v3(dv[2], acceleration); 02172 mul_v3_fl(dv[2], dtime); 02173 02174 add_v3_v3v3(states[3].co, states->co, dx[2]); 02175 add_v3_v3v3(states[3].vel, states->vel, dv[2]); 02176 states[3].time = dtime; 02177 /*fra=cfra;*/ 02178 break; 02179 case 3: 02180 add_v3_v3v3(dx[3], states->vel, dv[2]); 02181 mul_v3_fl(dx[3], dtime); 02182 copy_v3_v3(dv[3], acceleration); 02183 mul_v3_fl(dv[3], dtime); 02184 02185 madd_v3_v3v3fl(pa->state.co, states->co, dx[0], 1.0f/6.0f); 02186 madd_v3_v3fl(pa->state.co, dx[1], 1.0f/3.0f); 02187 madd_v3_v3fl(pa->state.co, dx[2], 1.0f/3.0f); 02188 madd_v3_v3fl(pa->state.co, dx[3], 1.0f/6.0f); 02189 02190 madd_v3_v3v3fl(pa->state.vel, states->vel, dv[0], 1.0f/6.0f); 02191 madd_v3_v3fl(pa->state.vel, dv[1], 1.0f/3.0f); 02192 madd_v3_v3fl(pa->state.vel, dv[2], 1.0f/3.0f); 02193 madd_v3_v3fl(pa->state.vel, dv[3], 1.0f/6.0f); 02194 } 02195 break; 02196 case PART_INT_VERLET: /* Verlet integration */ 02197 madd_v3_v3v3fl(pa->state.vel, pa->prev_state.vel, acceleration, dtime); 02198 madd_v3_v3v3fl(pa->state.co, pa->prev_state.co, pa->state.vel, dtime); 02199 02200 sub_v3_v3v3(pa->state.vel, pa->state.co, oldpos); 02201 mul_v3_fl(pa->state.vel, 1.0f/dtime); 02202 break; 02203 } 02204 } 02205 } 02206 02207 /********************************************************************************************************* 02208 SPH fluid physics 02209 02210 In theory, there could be unlimited implementation of SPH simulators 02211 02212 This code uses in some parts adapted algorithms from the pseudo code as outlined in the Research paper: 02213 02214 Titled: Particle-based Viscoelastic Fluid Simulation. 02215 Authors: Simon Clavet, Philippe Beaudoin and Pierre Poulin 02216 Website: http://www.iro.umontreal.ca/labs/infographie/papers/Clavet-2005-PVFS/ 02217 02218 Presented at Siggraph, (2005) 02219 02220 ***********************************************************************************************************/ 02221 #define PSYS_FLUID_SPRINGS_INITIAL_SIZE 256 02222 static ParticleSpring *sph_spring_add(ParticleSystem *psys, ParticleSpring *spring) 02223 { 02224 /* Are more refs required? */ 02225 if(psys->alloc_fluidsprings == 0 || psys->fluid_springs == NULL) { 02226 psys->alloc_fluidsprings = PSYS_FLUID_SPRINGS_INITIAL_SIZE; 02227 psys->fluid_springs = (ParticleSpring*)MEM_callocN(psys->alloc_fluidsprings * sizeof(ParticleSpring), "Particle Fluid Springs"); 02228 } 02229 else if(psys->tot_fluidsprings == psys->alloc_fluidsprings) { 02230 /* Double the number of refs allocated */ 02231 psys->alloc_fluidsprings *= 2; 02232 psys->fluid_springs = (ParticleSpring*)MEM_reallocN(psys->fluid_springs, psys->alloc_fluidsprings * sizeof(ParticleSpring)); 02233 } 02234 02235 memcpy(psys->fluid_springs + psys->tot_fluidsprings, spring, sizeof(ParticleSpring)); 02236 psys->tot_fluidsprings++; 02237 02238 return psys->fluid_springs + psys->tot_fluidsprings - 1; 02239 } 02240 static void sph_spring_delete(ParticleSystem *psys, int j) 02241 { 02242 if (j != psys->tot_fluidsprings - 1) 02243 psys->fluid_springs[j] = psys->fluid_springs[psys->tot_fluidsprings - 1]; 02244 02245 psys->tot_fluidsprings--; 02246 02247 if (psys->tot_fluidsprings < psys->alloc_fluidsprings/2 && psys->alloc_fluidsprings > PSYS_FLUID_SPRINGS_INITIAL_SIZE){ 02248 psys->alloc_fluidsprings /= 2; 02249 psys->fluid_springs = (ParticleSpring*)MEM_reallocN(psys->fluid_springs, psys->alloc_fluidsprings * sizeof(ParticleSpring)); 02250 } 02251 } 02252 static void sph_springs_modify(ParticleSystem *psys, float dtime){ 02253 SPHFluidSettings *fluid = psys->part->fluid; 02254 ParticleData *pa1, *pa2; 02255 ParticleSpring *spring = psys->fluid_springs; 02256 02257 float h, d, Rij[3], rij, Lij; 02258 int i; 02259 02260 float yield_ratio = fluid->yield_ratio; 02261 float plasticity = fluid->plasticity_constant; 02262 /* scale things according to dtime */ 02263 float timefix = 25.f * dtime; 02264 02265 if((fluid->flag & SPH_VISCOELASTIC_SPRINGS)==0 || fluid->spring_k == 0.f) 02266 return; 02267 02268 /* Loop through the springs */ 02269 for(i=0; i<psys->tot_fluidsprings; i++, spring++) { 02270 pa1 = psys->particles + spring->particle_index[0]; 02271 pa2 = psys->particles + spring->particle_index[1]; 02272 02273 sub_v3_v3v3(Rij, pa2->prev_state.co, pa1->prev_state.co); 02274 rij = normalize_v3(Rij); 02275 02276 /* adjust rest length */ 02277 Lij = spring->rest_length; 02278 d = yield_ratio * timefix * Lij; 02279 02280 if (rij > Lij + d) // Stretch 02281 spring->rest_length += plasticity * (rij - Lij - d) * timefix; 02282 else if(rij < Lij - d) // Compress 02283 spring->rest_length -= plasticity * (Lij - d - rij) * timefix; 02284 02285 h = 4.f*pa1->size; 02286 02287 if(spring->rest_length > h) 02288 spring->delete_flag = 1; 02289 } 02290 02291 /* Loop through springs backwaqrds - for efficient delete function */ 02292 for (i=psys->tot_fluidsprings-1; i >= 0; i--) { 02293 if(psys->fluid_springs[i].delete_flag) 02294 sph_spring_delete(psys, i); 02295 } 02296 } 02297 static EdgeHash *sph_springhash_build(ParticleSystem *psys) 02298 { 02299 EdgeHash *springhash = NULL; 02300 ParticleSpring *spring; 02301 int i = 0; 02302 02303 springhash = BLI_edgehash_new(); 02304 02305 for(i=0, spring=psys->fluid_springs; i<psys->tot_fluidsprings; i++, spring++) 02306 BLI_edgehash_insert(springhash, spring->particle_index[0], spring->particle_index[1], SET_INT_IN_POINTER(i+1)); 02307 02308 return springhash; 02309 } 02310 02311 typedef struct SPHNeighbor 02312 { 02313 ParticleSystem *psys; 02314 int index; 02315 } SPHNeighbor; 02316 typedef struct SPHRangeData 02317 { 02318 SPHNeighbor neighbors[128]; 02319 int tot_neighbors; 02320 02321 float density, near_density; 02322 float h; 02323 02324 ParticleSystem *npsys; 02325 ParticleData *pa; 02326 02327 float massfac; 02328 int use_size; 02329 } SPHRangeData; 02330 typedef struct SPHData { 02331 ParticleSystem *psys[10]; 02332 ParticleData *pa; 02333 float mass; 02334 EdgeHash *eh; 02335 float *gravity; 02336 }SPHData; 02337 static void sph_density_accum_cb(void *userdata, int index, float squared_dist) 02338 { 02339 SPHRangeData *pfr = (SPHRangeData *)userdata; 02340 ParticleData *npa = pfr->npsys->particles + index; 02341 float q; 02342 02343 if(npa == pfr->pa || squared_dist < FLT_EPSILON) 02344 return; 02345 02346 /* Ugh! One particle has over 128 neighbors! Really shouldn't happen, 02347 * but even if it does it shouldn't do any terrible harm if all are 02348 * not taken into account - jahka 02349 */ 02350 if(pfr->tot_neighbors >= 128) 02351 return; 02352 02353 pfr->neighbors[pfr->tot_neighbors].index = index; 02354 pfr->neighbors[pfr->tot_neighbors].psys = pfr->npsys; 02355 pfr->tot_neighbors++; 02356 02357 q = (1.f - sqrtf(squared_dist)/pfr->h) * pfr->massfac; 02358 02359 if(pfr->use_size) 02360 q *= npa->size; 02361 02362 pfr->density += q*q; 02363 pfr->near_density += q*q*q; 02364 } 02365 static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, float *UNUSED(impulse)) 02366 { 02367 SPHData *sphdata = (SPHData *)sphdata_v; 02368 ParticleSystem **psys = sphdata->psys; 02369 ParticleData *pa = sphdata->pa; 02370 SPHFluidSettings *fluid = psys[0]->part->fluid; 02371 ParticleSpring *spring = NULL; 02372 SPHRangeData pfr; 02373 SPHNeighbor *pfn; 02374 float mass = sphdata->mass; 02375 float *gravity = sphdata->gravity; 02376 EdgeHash *springhash = sphdata->eh; 02377 02378 float q, u, rij, dv[3]; 02379 float pressure, near_pressure; 02380 02381 float visc = fluid->viscosity_omega; 02382 float stiff_visc = fluid->viscosity_beta * (fluid->flag & SPH_FAC_VISCOSITY ? fluid->viscosity_omega : 1.f); 02383 02384 float inv_mass = 1.0f/mass; 02385 float spring_constant = fluid->spring_k; 02386 02387 float h = fluid->radius * (fluid->flag & SPH_FAC_RADIUS ? 4.f*pa->size : 1.f); /* 4.0 seems to be a pretty good value */ 02388 float rest_density = fluid->rest_density * (fluid->flag & SPH_FAC_DENSITY ? 4.77f : 1.f); /* 4.77 is an experimentally determined density factor */ 02389 float rest_length = fluid->rest_length * (fluid->flag & SPH_FAC_REST_LENGTH ? 2.588f * pa->size : 1.f); 02390 02391 float stiffness = fluid->stiffness_k; 02392 float stiffness_near_fac = fluid->stiffness_knear * (fluid->flag & SPH_FAC_REPULSION ? fluid->stiffness_k : 1.f); 02393 02394 ParticleData *npa; 02395 float vec[3]; 02396 float vel[3]; 02397 float co[3]; 02398 02399 int i, spring_index, index = pa - psys[0]->particles; 02400 02401 pfr.tot_neighbors = 0; 02402 pfr.density = pfr.near_density = 0.f; 02403 pfr.h = h; 02404 pfr.pa = pa; 02405 02406 for(i=0; i<10 && psys[i]; i++) { 02407 pfr.npsys = psys[i]; 02408 pfr.massfac = psys[i]->part->mass*inv_mass; 02409 pfr.use_size = psys[i]->part->flag & PART_SIZEMASS; 02410 02411 BLI_bvhtree_range_query(psys[i]->bvhtree, state->co, h, sph_density_accum_cb, &pfr); 02412 } 02413 02414 pressure = stiffness * (pfr.density - rest_density); 02415 near_pressure = stiffness_near_fac * pfr.near_density; 02416 02417 pfn = pfr.neighbors; 02418 for(i=0; i<pfr.tot_neighbors; i++, pfn++) { 02419 npa = pfn->psys->particles + pfn->index; 02420 02421 madd_v3_v3v3fl(co, npa->prev_state.co, npa->prev_state.vel, state->time); 02422 02423 sub_v3_v3v3(vec, co, state->co); 02424 rij = normalize_v3(vec); 02425 02426 q = (1.f - rij/h) * pfn->psys->part->mass * inv_mass; 02427 02428 if(pfn->psys->part->flag & PART_SIZEMASS) 02429 q *= npa->size; 02430 02431 copy_v3_v3(vel, npa->prev_state.vel); 02432 02433 /* Double Density Relaxation */ 02434 madd_v3_v3fl(force, vec, -(pressure + near_pressure*q)*q); 02435 02436 /* Viscosity */ 02437 if(visc > 0.f || stiff_visc > 0.f) { 02438 sub_v3_v3v3(dv, vel, state->vel); 02439 u = dot_v3v3(vec, dv); 02440 02441 if(u < 0.f && visc > 0.f) 02442 madd_v3_v3fl(force, vec, 0.5f * q * visc * u ); 02443 02444 if(u > 0.f && stiff_visc > 0.f) 02445 madd_v3_v3fl(force, vec, 0.5f * q * stiff_visc * u ); 02446 } 02447 02448 if(spring_constant > 0.f) { 02449 /* Viscoelastic spring force */ 02450 if (pfn->psys == psys[0] && fluid->flag & SPH_VISCOELASTIC_SPRINGS && springhash) { 02451 spring_index = GET_INT_FROM_POINTER(BLI_edgehash_lookup(springhash, index, pfn->index)); 02452 02453 if(spring_index) { 02454 spring = psys[0]->fluid_springs + spring_index - 1; 02455 02456 madd_v3_v3fl(force, vec, -10.f * spring_constant * (1.f - rij/h) * (spring->rest_length - rij)); 02457 } 02458 else if(fluid->spring_frames == 0 || (pa->prev_state.time-pa->time) <= fluid->spring_frames){ 02459 ParticleSpring temp_spring; 02460 temp_spring.particle_index[0] = index; 02461 temp_spring.particle_index[1] = pfn->index; 02462 temp_spring.rest_length = (fluid->flag & SPH_CURRENT_REST_LENGTH) ? rij : rest_length; 02463 temp_spring.delete_flag = 0; 02464 02465 sph_spring_add(psys[0], &temp_spring); 02466 } 02467 } 02468 else {/* PART_SPRING_HOOKES - Hooke's spring force */ 02469 madd_v3_v3fl(force, vec, -10.f * spring_constant * (1.f - rij/h) * (rest_length - rij)); 02470 } 02471 } 02472 } 02473 02474 /* Artificial buoyancy force in negative gravity direction */ 02475 if (fluid->buoyancy > 0.f && gravity) 02476 madd_v3_v3fl(force, gravity, fluid->buoyancy * (pfr.density-rest_density)); 02477 } 02478 02479 static void sph_integrate(ParticleSimulationData *sim, ParticleData *pa, float dfra, float *gravity, EdgeHash *springhash){ 02480 ParticleTarget *pt; 02481 int i; 02482 02483 ParticleSettings *part = sim->psys->part; 02484 // float timestep = psys_get_timestep(sim); // UNUSED 02485 float pa_mass = part->mass * (part->flag & PART_SIZEMASS ? pa->size : 1.f); 02486 float dtime = dfra*psys_get_timestep(sim); 02487 // int steps = 1; // UNUSED 02488 float effector_acceleration[3]; 02489 SPHData sphdata; 02490 02491 sphdata.psys[0] = sim->psys; 02492 for(i=1, pt=sim->psys->targets.first; i<10; i++, pt=(pt?pt->next:NULL)) 02493 sphdata.psys[i] = pt ? psys_get_target_system(sim->ob, pt) : NULL; 02494 02495 sphdata.pa = pa; 02496 sphdata.gravity = gravity; 02497 sphdata.mass = pa_mass; 02498 sphdata.eh = springhash; 02499 02500 /* restore previous state and treat gravity & effectors as external acceleration*/ 02501 sub_v3_v3v3(effector_acceleration, pa->state.vel, pa->prev_state.vel); 02502 mul_v3_fl(effector_acceleration, 1.f/dtime); 02503 02504 copy_particle_key(&pa->state, &pa->prev_state, 0); 02505 02506 integrate_particle(part, pa, dtime, effector_acceleration, sph_force_cb, &sphdata); 02507 } 02508 02509 /************************************************/ 02510 /* Basic physics */ 02511 /************************************************/ 02512 typedef struct EfData 02513 { 02514 ParticleTexture ptex; 02515 ParticleSimulationData *sim; 02516 ParticleData *pa; 02517 } EfData; 02518 static void basic_force_cb(void *efdata_v, ParticleKey *state, float *force, float *impulse) 02519 { 02520 EfData *efdata = (EfData *)efdata_v; 02521 ParticleSimulationData *sim = efdata->sim; 02522 ParticleSettings *part = sim->psys->part; 02523 ParticleData *pa = efdata->pa; 02524 EffectedPoint epoint; 02525 02526 /* add effectors */ 02527 pd_point_from_particle(efdata->sim, efdata->pa, state, &epoint); 02528 if(part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR) 02529 pdDoEffectors(sim->psys->effectors, sim->colliders, part->effector_weights, &epoint, force, impulse); 02530 02531 mul_v3_fl(force, efdata->ptex.field); 02532 mul_v3_fl(impulse, efdata->ptex.field); 02533 02534 /* calculate air-particle interaction */ 02535 if(part->dragfac != 0.0f) 02536 madd_v3_v3fl(force, state->vel, -part->dragfac * pa->size * pa->size * len_v3(state->vel)); 02537 02538 /* brownian force */ 02539 if(part->brownfac != 0.0f){ 02540 force[0] += (BLI_frand()-0.5f) * part->brownfac; 02541 force[1] += (BLI_frand()-0.5f) * part->brownfac; 02542 force[2] += (BLI_frand()-0.5f) * part->brownfac; 02543 } 02544 } 02545 /* gathers all forces that effect particles and calculates a new state for the particle */ 02546 static void basic_integrate(ParticleSimulationData *sim, int p, float dfra, float cfra) 02547 { 02548 ParticleSettings *part = sim->psys->part; 02549 ParticleData *pa = sim->psys->particles + p; 02550 ParticleKey tkey; 02551 float dtime=dfra*psys_get_timestep(sim), time; 02552 float *gravity = NULL, gr[3]; 02553 EfData efdata; 02554 02555 psys_get_texture(sim, pa, &efdata.ptex, PAMAP_PHYSICS, cfra); 02556 02557 efdata.pa = pa; 02558 efdata.sim = sim; 02559 02560 /* add global acceleration (gravitation) */ 02561 if(psys_uses_gravity(sim) 02562 /* normal gravity is too strong for hair so it's disabled by default */ 02563 && (part->type != PART_HAIR || part->effector_weights->flag & EFF_WEIGHT_DO_HAIR)) { 02564 zero_v3(gr); 02565 madd_v3_v3fl(gr, sim->scene->physics_settings.gravity, part->effector_weights->global_gravity * efdata.ptex.gravity); 02566 gravity = gr; 02567 } 02568 02569 /* maintain angular velocity */ 02570 copy_v3_v3(pa->state.ave, pa->prev_state.ave); 02571 02572 integrate_particle(part, pa, dtime, gravity, basic_force_cb, &efdata); 02573 02574 /* damp affects final velocity */ 02575 if(part->dampfac != 0.f) 02576 mul_v3_fl(pa->state.vel, 1.f - part->dampfac * efdata.ptex.damp * 25.f * dtime); 02577 02578 //VECCOPY(pa->state.ave, states->ave); 02579 02580 /* finally we do guides */ 02581 time=(cfra-pa->time)/pa->lifetime; 02582 CLAMP(time, 0.0f, 1.0f); 02583 02584 VECCOPY(tkey.co,pa->state.co); 02585 VECCOPY(tkey.vel,pa->state.vel); 02586 tkey.time=pa->state.time; 02587 02588 if(part->type != PART_HAIR) { 02589 if(do_guides(sim->psys->effectors, &tkey, p, time)) { 02590 VECCOPY(pa->state.co,tkey.co); 02591 /* guides don't produce valid velocity */ 02592 VECSUB(pa->state.vel,tkey.co,pa->prev_state.co); 02593 mul_v3_fl(pa->state.vel,1.0f/dtime); 02594 pa->state.time=tkey.time; 02595 } 02596 } 02597 } 02598 static void basic_rotate(ParticleSettings *part, ParticleData *pa, float dfra, float timestep) 02599 { 02600 float rotfac, rot1[4], rot2[4]={1.0,0.0,0.0,0.0}, dtime=dfra*timestep; 02601 02602 if((part->flag & PART_ROT_DYN)==0){ 02603 if(part->avemode==PART_AVE_SPIN){ 02604 float angle; 02605 float len1 = len_v3(pa->prev_state.vel); 02606 float len2 = len_v3(pa->state.vel); 02607 02608 if(len1==0.0f || len2==0.0f) 02609 pa->state.ave[0]=pa->state.ave[1]=pa->state.ave[2]=0.0f; 02610 else{ 02611 cross_v3_v3v3(pa->state.ave,pa->prev_state.vel,pa->state.vel); 02612 normalize_v3(pa->state.ave); 02613 angle=dot_v3v3(pa->prev_state.vel,pa->state.vel)/(len1*len2); 02614 mul_v3_fl(pa->state.ave,saacos(angle)/dtime); 02615 } 02616 02617 axis_angle_to_quat(rot2,pa->state.vel,dtime*part->avefac); 02618 } 02619 } 02620 02621 rotfac=len_v3(pa->state.ave); 02622 if(rotfac == 0.0f){ /* unit_qt(in VecRotToQuat) doesn't give unit quat [1,0,0,0]?? */ 02623 rot1[0]=1.0f; 02624 rot1[1]=rot1[2]=rot1[3]=0; 02625 } 02626 else{ 02627 axis_angle_to_quat(rot1,pa->state.ave,rotfac*dtime); 02628 } 02629 mul_qt_qtqt(pa->state.rot,rot1,pa->prev_state.rot); 02630 mul_qt_qtqt(pa->state.rot,rot2,pa->state.rot); 02631 02632 /* keep rotation quat in good health */ 02633 normalize_qt(pa->state.rot); 02634 } 02635 02636 /************************************************/ 02637 /* Collisions */ 02638 /************************************************/ 02639 #define COLLISION_MAX_COLLISIONS 10 02640 #define COLLISION_MIN_RADIUS 0.001f 02641 #define COLLISION_MIN_DISTANCE 0.0001f 02642 #define COLLISION_ZERO 0.00001f 02643 typedef float (*NRDistanceFunc)(float *p, float radius, ParticleCollisionElement *pce, float *nor); 02644 static float nr_signed_distance_to_plane(float *p, float radius, ParticleCollisionElement *pce, float *nor) 02645 { 02646 float p0[3], e1[3], e2[3], d; 02647 02648 sub_v3_v3v3(e1, pce->x1, pce->x0); 02649 sub_v3_v3v3(e2, pce->x2, pce->x0); 02650 sub_v3_v3v3(p0, p, pce->x0); 02651 02652 cross_v3_v3v3(nor, e1, e2); 02653 normalize_v3(nor); 02654 02655 d = dot_v3v3(p0, nor); 02656 02657 if(pce->inv_nor == -1) { 02658 if(d < 0.f) 02659 pce->inv_nor = 1; 02660 else 02661 pce->inv_nor = 0; 02662 } 02663 02664 if(pce->inv_nor == 1) { 02665 mul_v3_fl(nor, -1.f); 02666 d = -d; 02667 } 02668 02669 return d - radius; 02670 } 02671 static float nr_distance_to_edge(float *p, float radius, ParticleCollisionElement *pce, float *UNUSED(nor)) 02672 { 02673 float v0[3], v1[3], v2[3], c[3]; 02674 02675 sub_v3_v3v3(v0, pce->x1, pce->x0); 02676 sub_v3_v3v3(v1, p, pce->x0); 02677 sub_v3_v3v3(v2, p, pce->x1); 02678 02679 cross_v3_v3v3(c, v1, v2); 02680 02681 return fabsf(len_v3(c)/len_v3(v0)) - radius; 02682 } 02683 static float nr_distance_to_vert(float *p, float radius, ParticleCollisionElement *pce, float *UNUSED(nor)) 02684 { 02685 return len_v3v3(p, pce->x0) - radius; 02686 } 02687 static void collision_interpolate_element(ParticleCollisionElement *pce, float t, float fac, ParticleCollision *col) 02688 { 02689 /* t is the current time for newton rhapson */ 02690 /* fac is the starting factor for current collision iteration */ 02691 /* the col->fac's are factors for the particle subframe step start and end during collision modifier step */ 02692 float f = fac + t*(1.f-fac); 02693 float mul = col->fac1 + f * (col->fac2-col->fac1); 02694 if(pce->tot > 0) { 02695 madd_v3_v3v3fl(pce->x0, pce->x[0], pce->v[0], mul); 02696 02697 if(pce->tot > 1) { 02698 madd_v3_v3v3fl(pce->x1, pce->x[1], pce->v[1], mul); 02699 02700 if(pce->tot > 2) 02701 madd_v3_v3v3fl(pce->x2, pce->x[2], pce->v[2], mul); 02702 } 02703 } 02704 } 02705 static void collision_point_velocity(ParticleCollisionElement *pce) 02706 { 02707 float v[3]; 02708 02709 copy_v3_v3(pce->vel, pce->v[0]); 02710 02711 if(pce->tot > 1) { 02712 sub_v3_v3v3(v, pce->v[1], pce->v[0]); 02713 madd_v3_v3fl(pce->vel, v, pce->uv[0]); 02714 02715 if(pce->tot > 2) { 02716 sub_v3_v3v3(v, pce->v[2], pce->v[0]); 02717 madd_v3_v3fl(pce->vel, v, pce->uv[1]); 02718 } 02719 } 02720 } 02721 static float collision_point_distance_with_normal(float p[3], ParticleCollisionElement *pce, float fac, ParticleCollision *col, float *nor) 02722 { 02723 if(fac >= 0.f) 02724 collision_interpolate_element(pce, 0.f, fac, col); 02725 02726 switch(pce->tot) { 02727 case 1: 02728 { 02729 sub_v3_v3v3(nor, p, pce->x0); 02730 return normalize_v3(nor); 02731 } 02732 case 2: 02733 { 02734 float u, e[3], vec[3]; 02735 sub_v3_v3v3(e, pce->x1, pce->x0); 02736 sub_v3_v3v3(vec, p, pce->x0); 02737 u = dot_v3v3(vec, e) / dot_v3v3(e, e); 02738 02739 madd_v3_v3v3fl(nor, vec, e, -u); 02740 return normalize_v3(nor); 02741 } 02742 case 3: 02743 return nr_signed_distance_to_plane(p, 0.f, pce, nor); 02744 } 02745 return 0; 02746 } 02747 static void collision_point_on_surface(float p[3], ParticleCollisionElement *pce, float fac, ParticleCollision *col, float *co) 02748 { 02749 collision_interpolate_element(pce, 0.f, fac, col); 02750 02751 switch(pce->tot) { 02752 case 1: 02753 { 02754 sub_v3_v3v3(co, p, pce->x0); 02755 normalize_v3(co); 02756 madd_v3_v3v3fl(co, pce->x0, co, col->radius); 02757 break; 02758 } 02759 case 2: 02760 { 02761 float u, e[3], vec[3], nor[3]; 02762 sub_v3_v3v3(e, pce->x1, pce->x0); 02763 sub_v3_v3v3(vec, p, pce->x0); 02764 u = dot_v3v3(vec, e) / dot_v3v3(e, e); 02765 02766 madd_v3_v3v3fl(nor, vec, e, -u); 02767 normalize_v3(nor); 02768 02769 madd_v3_v3v3fl(co, pce->x0, e, pce->uv[0]); 02770 madd_v3_v3fl(co, nor, col->radius); 02771 break; 02772 } 02773 case 3: 02774 { 02775 float p0[3], e1[3], e2[3], nor[3]; 02776 02777 sub_v3_v3v3(e1, pce->x1, pce->x0); 02778 sub_v3_v3v3(e2, pce->x2, pce->x0); 02779 sub_v3_v3v3(p0, p, pce->x0); 02780 02781 cross_v3_v3v3(nor, e1, e2); 02782 normalize_v3(nor); 02783 02784 if(pce->inv_nor == 1) 02785 mul_v3_fl(nor, -1.f); 02786 02787 madd_v3_v3v3fl(co, pce->x0, nor, col->radius); 02788 madd_v3_v3fl(co, e1, pce->uv[0]); 02789 madd_v3_v3fl(co, e2, pce->uv[1]); 02790 break; 02791 } 02792 } 02793 } 02794 /* find first root in range [0-1] starting from 0 */ 02795 static float collision_newton_rhapson(ParticleCollision *col, float radius, ParticleCollisionElement *pce, NRDistanceFunc distance_func) 02796 { 02797 float t0, t1, d0, d1, dd, n[3]; 02798 int iter; 02799 02800 pce->inv_nor = -1; 02801 02802 /* start from the beginning */ 02803 t0 = 0.f; 02804 collision_interpolate_element(pce, t0, col->f, col); 02805 d0 = distance_func(col->co1, radius, pce, n); 02806 t1 = 0.001f; 02807 d1 = 0.f; 02808 02809 for(iter=0; iter<10; iter++) {//, itersum++) { 02810 /* get current location */ 02811 collision_interpolate_element(pce, t1, col->f, col); 02812 interp_v3_v3v3(pce->p, col->co1, col->co2, t1); 02813 02814 d1 = distance_func(pce->p, radius, pce, n); 02815 02816 /* no movement, so no collision */ 02817 if(d1 == d0) { 02818 return -1.f; 02819 } 02820 02821 /* particle already inside face, so report collision */ 02822 if(iter == 0 && d0 < 0.f && d0 > -radius) { 02823 copy_v3_v3(pce->p, col->co1); 02824 copy_v3_v3(pce->nor, n); 02825 pce->inside = 1; 02826 return 0.f; 02827 } 02828 02829 dd = (t1-t0)/(d1-d0); 02830 02831 t0 = t1; 02832 d0 = d1; 02833 02834 t1 -= d1*dd; 02835 02836 /* particle movin away from plane could also mean a strangely rotating face, so check from end */ 02837 if(iter == 0 && t1 < 0.f) { 02838 t0 = 1.f; 02839 collision_interpolate_element(pce, t0, col->f, col); 02840 d0 = distance_func(col->co2, radius, pce, n); 02841 t1 = 0.999f; 02842 d1 = 0.f; 02843 02844 continue; 02845 } 02846 else if(iter == 1 && (t1 < -COLLISION_ZERO || t1 > 1.f)) 02847 return -1.f; 02848 02849 if(d1 <= COLLISION_ZERO && d1 >= -COLLISION_ZERO) { 02850 if(t1 >= -COLLISION_ZERO && t1 <= 1.f) { 02851 if(distance_func == nr_signed_distance_to_plane) 02852 copy_v3_v3(pce->nor, n); 02853 02854 CLAMP(t1, 0.f, 1.f); 02855 02856 return t1; 02857 } 02858 else 02859 return -1.f; 02860 } 02861 } 02862 return -1.0; 02863 } 02864 static int collision_sphere_to_tri(ParticleCollision *col, float radius, ParticleCollisionElement *pce, float *t) 02865 { 02866 ParticleCollisionElement *result = &col->pce; 02867 float ct, u, v; 02868 02869 pce->inv_nor = -1; 02870 pce->inside = 0; 02871 02872 ct = collision_newton_rhapson(col, radius, pce, nr_signed_distance_to_plane); 02873 02874 if(ct >= 0.f && ct < *t && (result->inside==0 || pce->inside==1) ) { 02875 float e1[3], e2[3], p0[3]; 02876 float e1e1, e1e2, e1p0, e2e2, e2p0, inv; 02877 02878 sub_v3_v3v3(e1, pce->x1, pce->x0); 02879 sub_v3_v3v3(e2, pce->x2, pce->x0); 02880 /* XXX: add radius correction here? */ 02881 sub_v3_v3v3(p0, pce->p, pce->x0); 02882 02883 e1e1 = dot_v3v3(e1, e1); 02884 e1e2 = dot_v3v3(e1, e2); 02885 e1p0 = dot_v3v3(e1, p0); 02886 e2e2 = dot_v3v3(e2, e2); 02887 e2p0 = dot_v3v3(e2, p0); 02888 02889 inv = 1.f/(e1e1 * e2e2 - e1e2 * e1e2); 02890 u = (e2e2 * e1p0 - e1e2 * e2p0) * inv; 02891 v = (e1e1 * e2p0 - e1e2 * e1p0) * inv; 02892 02893 if(u>=0.f && u<=1.f && v>=0.f && u+v<=1.f) { 02894 *result = *pce; 02895 02896 /* normal already calculated in pce */ 02897 02898 result->uv[0] = u; 02899 result->uv[1] = v; 02900 02901 *t = ct; 02902 return 1; 02903 } 02904 } 02905 return 0; 02906 } 02907 static int collision_sphere_to_edges(ParticleCollision *col, float radius, ParticleCollisionElement *pce, float *t) 02908 { 02909 ParticleCollisionElement edge[3], *cur = NULL, *hit = NULL; 02910 ParticleCollisionElement *result = &col->pce; 02911 02912 float ct; 02913 int i; 02914 02915 for(i=0; i<3; i++) { 02916 /* in case of a quad, no need to check "edge" that goes through face twice */ 02917 if((pce->x[3] && i==2)) 02918 continue; 02919 02920 cur = edge+i; 02921 cur->x[0] = pce->x[i]; cur->x[1] = pce->x[(i+1)%3]; 02922 cur->v[0] = pce->v[i]; cur->v[1] = pce->v[(i+1)%3]; 02923 cur->tot = 2; 02924 cur->inside = 0; 02925 02926 ct = collision_newton_rhapson(col, radius, cur, nr_distance_to_edge); 02927 02928 if(ct >= 0.f && ct < *t) { 02929 float u, e[3], vec[3]; 02930 02931 sub_v3_v3v3(e, cur->x1, cur->x0); 02932 sub_v3_v3v3(vec, cur->p, cur->x0); 02933 u = dot_v3v3(vec, e) / dot_v3v3(e, e); 02934 02935 if(u < 0.f || u > 1.f) 02936 break; 02937 02938 *result = *cur; 02939 02940 madd_v3_v3v3fl(result->nor, vec, e, -u); 02941 normalize_v3(result->nor); 02942 02943 result->uv[0] = u; 02944 02945 02946 hit = cur; 02947 *t = ct; 02948 } 02949 02950 } 02951 02952 return hit != NULL; 02953 } 02954 static int collision_sphere_to_verts(ParticleCollision *col, float radius, ParticleCollisionElement *pce, float *t) 02955 { 02956 ParticleCollisionElement vert[3], *cur = NULL, *hit = NULL; 02957 ParticleCollisionElement *result = &col->pce; 02958 02959 float ct; 02960 int i; 02961 02962 for(i=0; i<3; i++) { 02963 /* in case of quad, only check one vert the first time */ 02964 if(pce->x[3] && i != 1) 02965 continue; 02966 02967 cur = vert+i; 02968 cur->x[0] = pce->x[i]; 02969 cur->v[0] = pce->v[i]; 02970 cur->tot = 1; 02971 cur->inside = 0; 02972 02973 ct = collision_newton_rhapson(col, radius, cur, nr_distance_to_vert); 02974 02975 if(ct >= 0.f && ct < *t) { 02976 *result = *cur; 02977 02978 sub_v3_v3v3(result->nor, cur->p, cur->x0); 02979 normalize_v3(result->nor); 02980 02981 hit = cur; 02982 *t = ct; 02983 } 02984 02985 } 02986 02987 return hit != NULL; 02988 } 02989 /* Callback for BVHTree near test */ 02990 void BKE_psys_collision_neartest_cb(void *userdata, int index, const BVHTreeRay *ray, BVHTreeRayHit *hit) 02991 { 02992 ParticleCollision *col = (ParticleCollision *) userdata; 02993 ParticleCollisionElement pce; 02994 MFace *face = col->md->mfaces + index; 02995 MVert *x = col->md->x; 02996 MVert *v = col->md->current_v; 02997 float t = hit->dist/col->original_ray_length; 02998 int collision = 0; 02999 03000 pce.x[0] = x[face->v1].co; 03001 pce.x[1] = x[face->v2].co; 03002 pce.x[2] = x[face->v3].co; 03003 pce.x[3] = face->v4 ? x[face->v4].co : NULL; 03004 03005 pce.v[0] = v[face->v1].co; 03006 pce.v[1] = v[face->v2].co; 03007 pce.v[2] = v[face->v3].co; 03008 pce.v[3] = face->v4 ? v[face->v4].co : NULL; 03009 03010 pce.tot = 3; 03011 pce.inside = 0; 03012 pce.index = index; 03013 03014 /* don't collide with same face again */ 03015 if(col->hit == col->current && col->pce.index == index && col->pce.tot == 3) 03016 return; 03017 03018 do 03019 { 03020 collision = collision_sphere_to_tri(col, ray->radius, &pce, &t); 03021 if(col->pce.inside == 0) { 03022 collision += collision_sphere_to_edges(col, ray->radius, &pce, &t); 03023 collision += collision_sphere_to_verts(col, ray->radius, &pce, &t); 03024 } 03025 03026 if(collision) { 03027 hit->dist = col->original_ray_length * t; 03028 hit->index = index; 03029 03030 collision_point_velocity(&col->pce); 03031 03032 col->hit = col->current; 03033 } 03034 03035 pce.x[1] = pce.x[2]; 03036 pce.x[2] = pce.x[3]; 03037 pce.x[3] = NULL; 03038 03039 pce.v[1] = pce.v[2]; 03040 pce.v[2] = pce.v[3]; 03041 pce.v[3] = NULL; 03042 03043 } while(pce.x[2]); 03044 } 03045 static int collision_detect(ParticleData *pa, ParticleCollision *col, BVHTreeRayHit *hit, ListBase *colliders) 03046 { 03047 ColliderCache *coll; 03048 float ray_dir[3]; 03049 03050 if(colliders->first == NULL) 03051 return 0; 03052 03053 sub_v3_v3v3(ray_dir, col->co2, col->co1); 03054 hit->index = -1; 03055 hit->dist = col->original_ray_length = len_v3(ray_dir); 03056 col->pce.inside = 0; 03057 03058 /* even if particle is stationary we want to check for moving colliders */ 03059 /* if hit.dist is zero the bvhtree_ray_cast will just ignore everything */ 03060 if(hit->dist == 0.0f) 03061 hit->dist = col->original_ray_length = 0.000001f; 03062 03063 for(coll = colliders->first; coll; coll=coll->next){ 03064 /* for boids: don't check with current ground object */ 03065 if(coll->ob == col->skip) 03066 continue; 03067 03068 /* particles should not collide with emitter at birth */ 03069 if(coll->ob == col->emitter && pa->time < col->cfra && pa->time >= col->old_cfra) 03070 continue; 03071 03072 col->current = coll->ob; 03073 col->md = coll->collmd; 03074 col->fac1 = (col->old_cfra - coll->collmd->time_x) / (coll->collmd->time_xnew - coll->collmd->time_x); 03075 col->fac2 = (col->cfra - coll->collmd->time_x) / (coll->collmd->time_xnew - coll->collmd->time_x); 03076 03077 if(col->md && col->md->bvhtree) 03078 BLI_bvhtree_ray_cast(col->md->bvhtree, col->co1, ray_dir, col->radius, hit, BKE_psys_collision_neartest_cb, col); 03079 } 03080 03081 return hit->index >= 0; 03082 } 03083 static int collision_response(ParticleData *pa, ParticleCollision *col, BVHTreeRayHit *hit, int kill, int dynamic_rotation) 03084 { 03085 ParticleCollisionElement *pce = &col->pce; 03086 PartDeflect *pd = col->hit->pd; 03087 float co[3]; /* point of collision */ 03088 float x = hit->dist/col->original_ray_length; /* location factor of collision between this iteration */ 03089 float f = col->f + x * (1.0f - col->f); /* time factor of collision between timestep */ 03090 float dt1 = (f - col->f) * col->total_time; /* time since previous collision (in seconds) */ 03091 float dt2 = (1.0f - f) * col->total_time; /* time left after collision (in seconds) */ 03092 int through = (BLI_frand() < pd->pdef_perm) ? 1 : 0; /* did particle pass through the collision surface? */ 03093 03094 /* calculate exact collision location */ 03095 interp_v3_v3v3(co, col->co1, col->co2, x); 03096 03097 /* particle dies in collision */ 03098 if(through == 0 && (kill || pd->flag & PDEFLE_KILL_PART)) { 03099 pa->alive = PARS_DYING; 03100 pa->dietime = col->old_cfra + (col->cfra - col->old_cfra) * f; 03101 03102 copy_v3_v3(pa->state.co, co); 03103 interp_v3_v3v3(pa->state.vel, pa->prev_state.vel, pa->state.vel, f); 03104 interp_qt_qtqt(pa->state.rot, pa->prev_state.rot, pa->state.rot, f); 03105 interp_v3_v3v3(pa->state.ave, pa->prev_state.ave, pa->state.ave, f); 03106 03107 /* particle is dead so we don't need to calculate further */ 03108 return 0; 03109 } 03110 /* figure out velocity and other data after collision */ 03111 else { 03112 float v0[3]; /* velocity directly before collision to be modified into velocity directly after collision */ 03113 float v0_nor[3];/* normal component of v0 */ 03114 float v0_tan[3];/* tangential component of v0 */ 03115 float vc_tan[3];/* tangential component of collision surface velocity */ 03116 float v0_dot, vc_dot; 03117 float damp = pd->pdef_damp + pd->pdef_rdamp * 2 * (BLI_frand() - 0.5f); 03118 float frict = pd->pdef_frict + pd->pdef_rfrict * 2 * (BLI_frand() - 0.5f); 03119 float distance, nor[3], dot; 03120 03121 CLAMP(damp,0.0f, 1.0f); 03122 CLAMP(frict,0.0f, 1.0f); 03123 03124 /* get exact velocity right before collision */ 03125 madd_v3_v3v3fl(v0, col->ve1, col->acc, dt1); 03126 03127 /* convert collider velocity from 1/framestep to 1/s TODO: here we assume 1 frame step for collision modifier */ 03128 mul_v3_fl(pce->vel, col->inv_timestep); 03129 03130 /* calculate tangential particle velocity */ 03131 v0_dot = dot_v3v3(pce->nor, v0); 03132 madd_v3_v3v3fl(v0_tan, v0, pce->nor, -v0_dot); 03133 03134 /* calculate tangential collider velocity */ 03135 vc_dot = dot_v3v3(pce->nor, pce->vel); 03136 madd_v3_v3v3fl(vc_tan, pce->vel, pce->nor, -vc_dot); 03137 03138 /* handle friction effects (tangential and angular velocity) */ 03139 if(frict > 0.0f) { 03140 /* angular <-> linear velocity */ 03141 if(dynamic_rotation) { 03142 float vr_tan[3], v1_tan[3], ave[3]; 03143 03144 /* linear velocity of particle surface */ 03145 cross_v3_v3v3(vr_tan, pce->nor, pa->state.ave); 03146 mul_v3_fl(vr_tan, pa->size); 03147 03148 /* change to coordinates that move with the collision plane */ 03149 sub_v3_v3v3(v1_tan, v0_tan, vc_tan); 03150 03151 /* The resulting velocity is a weighted average of particle cm & surface 03152 * velocity. This weight (related to particle's moment of inertia) could 03153 * be made a parameter for angular <-> linear conversion. 03154 */ 03155 madd_v3_v3fl(v1_tan, vr_tan, -0.4); 03156 mul_v3_fl(v1_tan, 1.0f/1.4f); /* 1/(1+0.4) */ 03157 03158 /* rolling friction is around 0.01 of sliding friction (could be made a parameter) */ 03159 mul_v3_fl(v1_tan, 1.0f - 0.01f * frict); 03160 03161 /* surface_velocity is opposite to cm velocity */ 03162 mul_v3_v3fl(vr_tan, v1_tan, -1.0f); 03163 03164 /* get back to global coordinates */ 03165 add_v3_v3(v1_tan, vc_tan); 03166 03167 /* convert to angular velocity*/ 03168 cross_v3_v3v3(ave, vr_tan, pce->nor); 03169 mul_v3_fl(ave, 1.0f/MAX2(pa->size, 0.001f)); 03170 03171 /* only friction will cause change in linear & angular velocity */ 03172 interp_v3_v3v3(pa->state.ave, pa->state.ave, ave, frict); 03173 interp_v3_v3v3(v0_tan, v0_tan, v1_tan, frict); 03174 } 03175 else { 03176 /* just basic friction (unphysical due to the friction model used in Blender) */ 03177 interp_v3_v3v3(v0_tan, v0_tan, vc_tan, frict); 03178 } 03179 } 03180 03181 /* stickness was possibly added before, so cancel that before calculating new normal velocity */ 03182 /* otherwise particles go flying out of the surface because of high reversed sticky velocity */ 03183 if(v0_dot < 0.0f) { 03184 v0_dot += pd->pdef_stickness; 03185 if(v0_dot > 0.0f) 03186 v0_dot = 0.0f; 03187 } 03188 03189 /* damping and flipping of velocity around normal */ 03190 v0_dot *= 1.0f - damp; 03191 vc_dot *= through ? damp : 1.0f; 03192 03193 /* calculate normal particle velocity */ 03194 /* special case for object hitting the particle from behind */ 03195 if(through==0 && ((vc_dot>0.0f && v0_dot>0.0f && vc_dot>v0_dot) || (vc_dot<0.0f && v0_dot<0.0f && vc_dot<v0_dot))) 03196 mul_v3_v3fl(v0_nor, pce->nor, vc_dot); 03197 else if(v0_dot > 0.f) 03198 mul_v3_v3fl(v0_nor, pce->nor, vc_dot + (through ? -1.0f : 1.0f) * v0_dot); 03199 else 03200 mul_v3_v3fl(v0_nor, pce->nor, vc_dot + (through ? 1.0f : -1.0f) * v0_dot); 03201 03202 /* combine components together again */ 03203 add_v3_v3v3(v0, v0_nor, v0_tan); 03204 03205 if(col->boid) { 03206 /* keep boids above ground */ 03207 BoidParticle *bpa = pa->boid; 03208 if(bpa->data.mode == eBoidMode_OnLand || co[2] <= col->boid_z) { 03209 co[2] = col->boid_z; 03210 v0[2] = 0.0f; 03211 } 03212 } 03213 03214 /* re-apply acceleration to final location and velocity */ 03215 madd_v3_v3v3fl(pa->state.co, co, v0, dt2); 03216 madd_v3_v3fl(pa->state.co, col->acc, 0.5f*dt2*dt2); 03217 madd_v3_v3v3fl(pa->state.vel, v0, col->acc, dt2); 03218 03219 /* make sure particle stays on the right side of the surface */ 03220 if(!through) { 03221 distance = collision_point_distance_with_normal(co, pce, -1.f, col, nor); 03222 03223 if(distance < col->radius + COLLISION_MIN_DISTANCE) 03224 madd_v3_v3fl(co, nor, col->radius + COLLISION_MIN_DISTANCE - distance); 03225 03226 dot = dot_v3v3(nor, v0); 03227 if(dot < 0.f) 03228 madd_v3_v3fl(v0, nor, -dot); 03229 03230 distance = collision_point_distance_with_normal(pa->state.co, pce, 1.f, col, nor); 03231 03232 if(distance < col->radius + COLLISION_MIN_DISTANCE) 03233 madd_v3_v3fl(pa->state.co, nor, col->radius + COLLISION_MIN_DISTANCE - distance); 03234 03235 dot = dot_v3v3(nor, pa->state.vel); 03236 if(dot < 0.f) 03237 madd_v3_v3fl(pa->state.vel, nor, -dot); 03238 } 03239 03240 /* add stickness to surface */ 03241 madd_v3_v3fl(pa->state.vel, pce->nor, -pd->pdef_stickness); 03242 03243 /* set coordinates for next iteration */ 03244 copy_v3_v3(col->co1, co); 03245 copy_v3_v3(col->co2, pa->state.co); 03246 03247 copy_v3_v3(col->ve1, v0); 03248 copy_v3_v3(col->ve2, pa->state.vel); 03249 03250 col->f = f; 03251 } 03252 03253 col->prev = col->hit; 03254 col->prev_index = hit->index; 03255 03256 return 1; 03257 } 03258 static void collision_fail(ParticleData *pa, ParticleCollision *col) 03259 { 03260 /* final chance to prevent total failure, so stick to the surface and hope for the best */ 03261 collision_point_on_surface(col->co1, &col->pce, 1.f, col, pa->state.co); 03262 03263 copy_v3_v3(pa->state.vel, col->pce.vel); 03264 mul_v3_fl(pa->state.vel, col->inv_timestep); 03265 03266 03267 /* printf("max iterations\n"); */ 03268 } 03269 03270 /* Particle - Mesh collision detection and response 03271 * Features: 03272 * -friction and damping 03273 * -angular momentum <-> linear momentum 03274 * -high accuracy by re-applying particle acceleration after collision 03275 * -handles moving, rotating and deforming meshes 03276 * -uses Newton-Rhapson iteration to find the collisions 03277 * -handles spherical particles and (nearly) point like particles 03278 */ 03279 static void collision_check(ParticleSimulationData *sim, int p, float dfra, float cfra){ 03280 ParticleSettings *part = sim->psys->part; 03281 ParticleData *pa = sim->psys->particles + p; 03282 ParticleCollision col; 03283 BVHTreeRayHit hit; 03284 int collision_count=0; 03285 03286 float timestep = psys_get_timestep(sim); 03287 03288 memset(&col, 0, sizeof(ParticleCollision)); 03289 03290 col.total_time = timestep * dfra; 03291 col.inv_timestep = 1.0f/timestep; 03292 03293 col.cfra = cfra; 03294 col.old_cfra = sim->psys->cfra; 03295 03296 /* get acceleration (from gravity, forcefields etc. to be re-applied in collision response) */ 03297 sub_v3_v3v3(col.acc, pa->state.vel, pa->prev_state.vel); 03298 mul_v3_fl(col.acc, 1.f/col.total_time); 03299 03300 /* set values for first iteration */ 03301 copy_v3_v3(col.co1, pa->prev_state.co); 03302 copy_v3_v3(col.co2, pa->state.co); 03303 copy_v3_v3(col.ve1, pa->prev_state.vel); 03304 copy_v3_v3(col.ve2, pa->state.vel); 03305 col.f = 0.0f; 03306 03307 col.radius = ((part->flag & PART_SIZE_DEFL) || (part->phystype == PART_PHYS_BOIDS)) ? pa->size : COLLISION_MIN_RADIUS; 03308 03309 /* override for boids */ 03310 if(part->phystype == PART_PHYS_BOIDS && part->boids->options & BOID_ALLOW_LAND) { 03311 col.boid = 1; 03312 col.boid_z = pa->state.co[2]; 03313 col.skip = pa->boid->ground; 03314 } 03315 03316 /* 10 iterations to catch multiple collisions */ 03317 while(collision_count < COLLISION_MAX_COLLISIONS){ 03318 if(collision_detect(pa, &col, &hit, sim->colliders)) { 03319 03320 collision_count++; 03321 03322 if(collision_count == COLLISION_MAX_COLLISIONS) 03323 collision_fail(pa, &col); 03324 else if(collision_response(pa, &col, &hit, part->flag & PART_DIE_ON_COL, part->flag & PART_ROT_DYN)==0) 03325 return; 03326 } 03327 else 03328 return; 03329 } 03330 } 03331 /************************************************/ 03332 /* Hair */ 03333 /************************************************/ 03334 /* check if path cache or children need updating and do it if needed */ 03335 static void psys_update_path_cache(ParticleSimulationData *sim, float cfra) 03336 { 03337 ParticleSystem *psys = sim->psys; 03338 ParticleSettings *part = psys->part; 03339 ParticleEditSettings *pset = &sim->scene->toolsettings->particle; 03340 int distr=0, alloc=0, skip=0; 03341 03342 if((psys->part->childtype && psys->totchild != get_psys_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET) 03343 alloc=1; 03344 03345 if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (sim->ob && sim->ob->mode & OB_MODE_WEIGHT_PAINT))) 03346 distr=1; 03347 03348 if(distr){ 03349 if(alloc) 03350 realloc_particles(sim, sim->psys->totpart); 03351 03352 if(get_psys_tot_child(sim->scene, psys)) { 03353 /* don't generate children while computing the hair keys */ 03354 if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) { 03355 distribute_particles(sim, PART_FROM_CHILD); 03356 03357 if(part->childtype==PART_CHILD_FACES && part->parents != 0.0f) 03358 psys_find_parents(sim); 03359 } 03360 } 03361 else 03362 psys_free_children(psys); 03363 } 03364 03365 if((part->type==PART_HAIR || psys->flag&PSYS_KEYED || psys->pointcache->flag & PTCACHE_BAKED)==0) 03366 skip = 1; /* only hair, keyed and baked stuff can have paths */ 03367 else if(part->ren_as != PART_DRAW_PATH && !(part->type==PART_HAIR && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR))) 03368 skip = 1; /* particle visualization must be set as path */ 03369 else if(!psys->renderdata) { 03370 if(part->draw_as != PART_DRAW_REND) 03371 skip = 1; /* draw visualization */ 03372 else if(psys->pointcache->flag & PTCACHE_BAKING) 03373 skip = 1; /* no need to cache paths while baking dynamics */ 03374 else if(psys_in_edit_mode(sim->scene, psys)) { 03375 if((pset->flag & PE_DRAW_PART)==0) 03376 skip = 1; 03377 else if(part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0) 03378 skip = 1; /* in edit mode paths are needed for child particles and dynamic hair */ 03379 } 03380 } 03381 03382 if(!skip) { 03383 psys_cache_paths(sim, cfra); 03384 03385 /* for render, child particle paths are computed on the fly */ 03386 if(part->childtype) { 03387 if(!psys->totchild) 03388 skip = 1; 03389 else if(psys->part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DONE)==0) 03390 skip = 1; 03391 03392 if(!skip) 03393 psys_cache_child_paths(sim, cfra, 0); 03394 } 03395 } 03396 else if(psys->pathcache) 03397 psys_free_path_cache(psys, NULL); 03398 } 03399 03400 static void do_hair_dynamics(ParticleSimulationData *sim) 03401 { 03402 ParticleSystem *psys = sim->psys; 03403 DerivedMesh *dm = psys->hair_in_dm; 03404 MVert *mvert = NULL; 03405 MEdge *medge = NULL; 03406 MDeformVert *dvert = NULL; 03407 HairKey *key; 03408 PARTICLE_P; 03409 int totpoint = 0; 03410 int totedge; 03411 int k; 03412 float hairmat[4][4]; 03413 03414 if(!psys->clmd) { 03415 psys->clmd = (ClothModifierData*)modifier_new(eModifierType_Cloth); 03416 psys->clmd->sim_parms->goalspring = 0.0f; 03417 psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_GOAL|CLOTH_SIMSETTINGS_FLAG_NO_SPRING_COMPRESS; 03418 psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF; 03419 } 03420 03421 /* create a dm from hair vertices */ 03422 LOOP_PARTICLES 03423 totpoint += pa->totkey; 03424 03425 totedge = totpoint; 03426 totpoint += psys->totpart; 03427 03428 if(dm && (totpoint != dm->getNumVerts(dm) || totedge != dm->getNumEdges(dm))) { 03429 dm->release(dm); 03430 dm = psys->hair_in_dm = NULL; 03431 } 03432 03433 if(!dm) { 03434 dm = psys->hair_in_dm = CDDM_new(totpoint, totedge, 0); 03435 DM_add_vert_layer(dm, CD_MDEFORMVERT, CD_CALLOC, NULL); 03436 } 03437 03438 mvert = CDDM_get_verts(dm); 03439 medge = CDDM_get_edges(dm); 03440 dvert = DM_get_vert_data_layer(dm, CD_MDEFORMVERT); 03441 03442 psys->clmd->sim_parms->vgroup_mass = 1; 03443 03444 /* make vgroup for pin roots etc.. */ 03445 psys->particles->hair_index = 1; 03446 LOOP_PARTICLES { 03447 if(p) 03448 pa->hair_index = (pa-1)->hair_index + (pa-1)->totkey + 1; 03449 03450 psys_mat_hair_to_object(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat); 03451 03452 for(k=0, key=pa->hair; k<pa->totkey; k++,key++) { 03453 03454 /* create fake root before actual root to resist bending */ 03455 if(k==0) { 03456 float temp[3]; 03457 VECSUB(temp, key->co, (key+1)->co); 03458 VECCOPY(mvert->co, key->co); 03459 VECADD(mvert->co, mvert->co, temp); 03460 mul_m4_v3(hairmat, mvert->co); 03461 mvert++; 03462 03463 medge->v1 = pa->hair_index - 1; 03464 medge->v2 = pa->hair_index; 03465 medge++; 03466 03467 if(dvert) { 03468 if(!dvert->totweight) { 03469 dvert->dw = MEM_callocN (sizeof(MDeformWeight), "deformWeight"); 03470 dvert->totweight = 1; 03471 } 03472 03473 dvert->dw->weight = 1.0f; 03474 dvert++; 03475 } 03476 } 03477 03478 VECCOPY(mvert->co, key->co); 03479 mul_m4_v3(hairmat, mvert->co); 03480 mvert++; 03481 03482 if(k) { 03483 medge->v1 = pa->hair_index + k - 1; 03484 medge->v2 = pa->hair_index + k; 03485 medge++; 03486 } 03487 03488 if(dvert) { 03489 if(!dvert->totweight) { 03490 dvert->dw = MEM_callocN (sizeof(MDeformWeight), "deformWeight"); 03491 dvert->totweight = 1; 03492 } 03493 /* roots should be 1.0, the rest can be anything from 0.0 to 1.0 */ 03494 dvert->dw->weight = key->weight; 03495 dvert++; 03496 } 03497 } 03498 } 03499 03500 if(psys->hair_out_dm) 03501 psys->hair_out_dm->release(psys->hair_out_dm); 03502 03503 psys->clmd->point_cache = psys->pointcache; 03504 psys->clmd->sim_parms->effector_weights = psys->part->effector_weights; 03505 03506 psys->hair_out_dm = clothModifier_do(psys->clmd, sim->scene, sim->ob, dm); 03507 03508 psys->clmd->sim_parms->effector_weights = NULL; 03509 } 03510 static void hair_step(ParticleSimulationData *sim, float cfra) 03511 { 03512 ParticleSystem *psys = sim->psys; 03513 ParticleSettings *part = psys->part; 03514 PARTICLE_P; 03515 float disp = (float)psys_get_current_display_percentage(psys)/100.0f; 03516 03517 LOOP_PARTICLES { 03518 pa->size = part->size; 03519 if(part->randsize > 0.0f) 03520 pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); 03521 03522 if(PSYS_FRAND(p) > disp) 03523 pa->flag |= PARS_NO_DISP; 03524 else 03525 pa->flag &= ~PARS_NO_DISP; 03526 } 03527 03528 if(psys->recalc & PSYS_RECALC_RESET) { 03529 /* need this for changing subsurf levels */ 03530 psys_calc_dmcache(sim->ob, sim->psmd->dm, psys); 03531 03532 if(psys->clmd) 03533 cloth_free_modifier(psys->clmd); 03534 } 03535 03536 /* dynamics with cloth simulation, psys->particles can be NULL with 0 particles [#25519] */ 03537 if(psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS && psys->particles) 03538 do_hair_dynamics(sim); 03539 03540 /* following lines were removed r29079 but cause bug [#22811], see report for details */ 03541 psys_update_effectors(sim); 03542 psys_update_path_cache(sim, cfra); 03543 03544 psys->flag |= PSYS_HAIR_UPDATED; 03545 } 03546 03547 static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra)){ 03548 Object *ob = sim->ob; 03549 ParticleSystem *psys = sim->psys; 03550 HairKey *key, *root; 03551 PARTICLE_P; 03552 03553 invert_m4_m4(ob->imat, ob->obmat); 03554 03555 psys->lattice= psys_get_lattice(sim); 03556 03557 if(psys->totpart==0) return; 03558 03559 /* save new keys for elements if needed */ 03560 LOOP_PARTICLES { 03561 /* first time alloc */ 03562 if(pa->totkey==0 || pa->hair==NULL) { 03563 pa->hair = MEM_callocN((psys->part->hair_step + 1) * sizeof(HairKey), "HairKeys"); 03564 pa->totkey = 0; 03565 } 03566 03567 key = root = pa->hair; 03568 key += pa->totkey; 03569 03570 /* convert from global to geometry space */ 03571 copy_v3_v3(key->co, pa->state.co); 03572 mul_m4_v3(ob->imat, key->co); 03573 03574 if(pa->totkey) { 03575 VECSUB(key->co, key->co, root->co); 03576 psys_vec_rot_to_face(sim->psmd->dm, pa, key->co); 03577 } 03578 03579 key->time = pa->state.time; 03580 03581 key->weight = 1.0f - key->time / 100.0f; 03582 03583 pa->totkey++; 03584 03585 /* root is always in the origin of hair space so we set it to be so after the last key is saved*/ 03586 if(pa->totkey == psys->part->hair_step + 1) 03587 root->co[0] = root->co[1] = root->co[2] = 0.0f; 03588 } 03589 } 03590 /************************************************/ 03591 /* System Core */ 03592 /************************************************/ 03593 /* unbaked particles are calculated dynamically */ 03594 static void dynamics_step(ParticleSimulationData *sim, float cfra) 03595 { 03596 ParticleSystem *psys = sim->psys; 03597 ParticleSettings *part=psys->part; 03598 BoidBrainData bbd; 03599 ParticleTexture ptex; 03600 PARTICLE_P; 03601 float timestep; 03602 /* frame & time changes */ 03603 float dfra, dtime; 03604 float birthtime, dietime; 03605 03606 /* where have we gone in time since last time */ 03607 dfra= cfra - psys->cfra; 03608 03609 timestep = psys_get_timestep(sim); 03610 dtime= dfra*timestep; 03611 03612 if(dfra < 0.0f) { 03613 LOOP_EXISTING_PARTICLES { 03614 psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra); 03615 pa->size = part->size*ptex.size; 03616 if(part->randsize > 0.0f) 03617 pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); 03618 03619 reset_particle(sim, pa, dtime, cfra); 03620 } 03621 return; 03622 } 03623 03624 BLI_srandom(31415926 + (int)cfra + psys->seed); 03625 03626 psys_update_effectors(sim); 03627 03628 if(part->type != PART_HAIR) 03629 sim->colliders = get_collider_cache(sim->scene, sim->ob, NULL); 03630 03631 /* initialize physics type specific stuff */ 03632 switch(part->phystype) { 03633 case PART_PHYS_BOIDS: 03634 { 03635 ParticleTarget *pt = psys->targets.first; 03636 bbd.sim = sim; 03637 bbd.part = part; 03638 bbd.cfra = cfra; 03639 bbd.dfra = dfra; 03640 bbd.timestep = timestep; 03641 03642 psys_update_particle_tree(psys, cfra); 03643 03644 boids_precalc_rules(part, cfra); 03645 03646 for(; pt; pt=pt->next) { 03647 if(pt->ob) 03648 psys_update_particle_tree(BLI_findlink(&pt->ob->particlesystem, pt->psys-1), cfra); 03649 } 03650 break; 03651 } 03652 case PART_PHYS_FLUID: 03653 { 03654 ParticleTarget *pt = psys->targets.first; 03655 psys_update_particle_bvhtree(psys, psys->cfra); 03656 03657 for(; pt; pt=pt->next) { /* Updating others systems particle tree for fluid-fluid interaction */ 03658 if(pt->ob) 03659 psys_update_particle_bvhtree(BLI_findlink(&pt->ob->particlesystem, pt->psys-1), psys->cfra); 03660 } 03661 break; 03662 } 03663 } 03664 /* initialize all particles for dynamics */ 03665 LOOP_SHOWN_PARTICLES { 03666 copy_particle_key(&pa->prev_state,&pa->state,1); 03667 03668 psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra); 03669 03670 pa->size = part->size*ptex.size; 03671 if(part->randsize > 0.0f) 03672 pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); 03673 03674 birthtime = pa->time; 03675 dietime = pa->dietime; 03676 03677 /* store this, so we can do multiple loops over particles */ 03678 pa->state.time = dfra; 03679 03680 if(dietime <= cfra && psys->cfra < dietime){ 03681 /* particle dies some time between this and last step */ 03682 pa->state.time = dietime - ((birthtime > psys->cfra) ? birthtime : psys->cfra); 03683 pa->alive = PARS_DYING; 03684 } 03685 else if(birthtime <= cfra && birthtime >= psys->cfra){ 03686 /* particle is born some time between this and last step*/ 03687 reset_particle(sim, pa, dfra*timestep, cfra); 03688 pa->alive = PARS_ALIVE; 03689 pa->state.time = cfra - birthtime; 03690 } 03691 else if(dietime < cfra){ 03692 /* nothing to be done when particle is dead */ 03693 } 03694 03695 /* only reset unborn particles if they're shown or if the particle is born soon*/ 03696 if(pa->alive==PARS_UNBORN 03697 && (part->flag & PART_UNBORN || cfra + psys->pointcache->step > pa->time)) 03698 reset_particle(sim, pa, dtime, cfra); 03699 else if(part->phystype == PART_PHYS_NO) 03700 reset_particle(sim, pa, dtime, cfra); 03701 03702 if(ELEM(pa->alive, PARS_ALIVE, PARS_DYING)==0 || (pa->flag & (PARS_UNEXIST|PARS_NO_DISP))) 03703 pa->state.time = -1.f; 03704 } 03705 03706 switch(part->phystype) { 03707 case PART_PHYS_NEWTON: 03708 { 03709 LOOP_DYNAMIC_PARTICLES { 03710 /* do global forces & effectors */ 03711 basic_integrate(sim, p, pa->state.time, cfra); 03712 03713 /* deflection */ 03714 if(sim->colliders) 03715 collision_check(sim, p, pa->state.time, cfra); 03716 03717 /* rotations */ 03718 basic_rotate(part, pa, pa->state.time, timestep); 03719 } 03720 break; 03721 } 03722 case PART_PHYS_BOIDS: 03723 { 03724 LOOP_DYNAMIC_PARTICLES { 03725 bbd.goal_ob = NULL; 03726 03727 boid_brain(&bbd, p, pa); 03728 03729 if(pa->alive != PARS_DYING) { 03730 boid_body(&bbd, pa); 03731 03732 /* deflection */ 03733 if(sim->colliders) 03734 collision_check(sim, p, pa->state.time, cfra); 03735 } 03736 } 03737 break; 03738 } 03739 case PART_PHYS_FLUID: 03740 { 03741 EdgeHash *springhash = sph_springhash_build(psys); 03742 float *gravity = NULL; 03743 03744 if(psys_uses_gravity(sim)) 03745 gravity = sim->scene->physics_settings.gravity; 03746 03747 LOOP_DYNAMIC_PARTICLES { 03748 /* do global forces & effectors */ 03749 basic_integrate(sim, p, pa->state.time, cfra); 03750 03751 /* actual fluids calculations */ 03752 sph_integrate(sim, pa, pa->state.time, gravity, springhash); 03753 03754 if(sim->colliders) 03755 collision_check(sim, p, pa->state.time, cfra); 03756 03757 /* SPH particles are not physical particles, just interpolation particles, thus rotation has not a direct sense for them */ 03758 basic_rotate(part, pa, pa->state.time, timestep); 03759 } 03760 03761 sph_springs_modify(psys, timestep); 03762 03763 if(springhash) { 03764 BLI_edgehash_free(springhash, NULL); 03765 springhash = NULL; 03766 } 03767 break; 03768 } 03769 } 03770 03771 /* finalize particle state and time after dynamics */ 03772 LOOP_DYNAMIC_PARTICLES { 03773 if(pa->alive == PARS_DYING){ 03774 pa->alive=PARS_DEAD; 03775 pa->state.time=pa->dietime; 03776 } 03777 else 03778 pa->state.time=cfra; 03779 } 03780 03781 free_collider_cache(&sim->colliders); 03782 } 03783 static void update_children(ParticleSimulationData *sim) 03784 { 03785 if((sim->psys->part->type == PART_HAIR) && (sim->psys->flag & PSYS_HAIR_DONE)==0) 03786 /* don't generate children while growing hair - waste of time */ 03787 psys_free_children(sim->psys); 03788 else if(sim->psys->part->childtype) { 03789 if(sim->psys->totchild != get_psys_tot_child(sim->scene, sim->psys)) 03790 distribute_particles(sim, PART_FROM_CHILD); 03791 else 03792 ; /* Children are up to date, nothing to do. */ 03793 } 03794 else 03795 psys_free_children(sim->psys); 03796 } 03797 /* updates cached particles' alive & other flags etc..*/ 03798 static void cached_step(ParticleSimulationData *sim, float cfra) 03799 { 03800 ParticleSystem *psys = sim->psys; 03801 ParticleSettings *part = psys->part; 03802 ParticleTexture ptex; 03803 PARTICLE_P; 03804 float disp, dietime; 03805 03806 psys_update_effectors(sim); 03807 03808 disp= (float)psys_get_current_display_percentage(psys)/100.0f; 03809 03810 LOOP_PARTICLES { 03811 psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra); 03812 pa->size = part->size*ptex.size; 03813 if(part->randsize > 0.0f) 03814 pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); 03815 03816 psys->lattice= psys_get_lattice(sim); 03817 03818 dietime = pa->dietime; 03819 03820 /* update alive status and push events */ 03821 if(pa->time > cfra) { 03822 pa->alive = PARS_UNBORN; 03823 if(part->flag & PART_UNBORN && (psys->pointcache->flag & PTCACHE_EXTERNAL) == 0) 03824 reset_particle(sim, pa, 0.0f, cfra); 03825 } 03826 else if(dietime <= cfra) 03827 pa->alive = PARS_DEAD; 03828 else 03829 pa->alive = PARS_ALIVE; 03830 03831 if(psys->lattice){ 03832 end_latt_deform(psys->lattice); 03833 psys->lattice= NULL; 03834 } 03835 03836 if(PSYS_FRAND(p) > disp) 03837 pa->flag |= PARS_NO_DISP; 03838 else 03839 pa->flag &= ~PARS_NO_DISP; 03840 } 03841 } 03842 03843 static void particles_fluid_step(ParticleSimulationData *sim, int UNUSED(cfra)) 03844 { 03845 ParticleSystem *psys = sim->psys; 03846 if(psys->particles){ 03847 MEM_freeN(psys->particles); 03848 psys->particles = 0; 03849 psys->totpart = 0; 03850 } 03851 03852 /* fluid sim particle import handling, actual loading of particles from file */ 03853 #ifndef DISABLE_ELBEEM 03854 { 03855 FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(sim->ob, eModifierType_Fluidsim); 03856 03857 if( fluidmd && fluidmd->fss) { 03858 FluidsimSettings *fss= fluidmd->fss; 03859 ParticleSettings *part = psys->part; 03860 ParticleData *pa=NULL; 03861 char filename[256]; 03862 char debugStrBuffer[256]; 03863 int curFrame = sim->scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading 03864 int p, j, totpart; 03865 int readMask, activeParts = 0, fileParts = 0; 03866 gzFile gzf; 03867 03868 // XXX if(ob==G.obedit) // off... 03869 // return; 03870 03871 // ok, start loading 03872 BLI_snprintf(filename, sizeof(filename), "%sfluidsurface_particles_####.gz", fss->surfdataPath); 03873 03874 BLI_path_abs(filename, G.main->name); 03875 BLI_path_frame(filename, curFrame, 0); // fixed #frame-no 03876 03877 gzf = gzopen(filename, "rb"); 03878 if (!gzf) { 03879 snprintf(debugStrBuffer,256,"readFsPartData::error - Unable to open file for reading '%s' \n", filename); 03880 // XXX bad level call elbeemDebugOut(debugStrBuffer); 03881 return; 03882 } 03883 03884 gzread(gzf, &totpart, sizeof(totpart)); 03885 totpart = (G.rendering)?totpart:(part->disp*totpart)/100; 03886 03887 part->totpart= totpart; 03888 part->sta=part->end = 1.0f; 03889 part->lifetime = sim->scene->r.efra + 1; 03890 03891 /* allocate particles */ 03892 realloc_particles(sim, part->totpart); 03893 03894 // set up reading mask 03895 readMask = fss->typeFlags; 03896 03897 for(p=0, pa=psys->particles; p<totpart; p++, pa++) { 03898 int ptype=0; 03899 03900 gzread(gzf, &ptype, sizeof( ptype )); 03901 if(ptype&readMask) { 03902 activeParts++; 03903 03904 gzread(gzf, &(pa->size), sizeof( float )); 03905 03906 pa->size /= 10.0f; 03907 03908 for(j=0; j<3; j++) { 03909 float wrf; 03910 gzread(gzf, &wrf, sizeof( wrf )); 03911 pa->state.co[j] = wrf; 03912 //fprintf(stderr,"Rj%d ",j); 03913 } 03914 for(j=0; j<3; j++) { 03915 float wrf; 03916 gzread(gzf, &wrf, sizeof( wrf )); 03917 pa->state.vel[j] = wrf; 03918 } 03919 03920 pa->state.ave[0] = pa->state.ave[1] = pa->state.ave[2] = 0.0f; 03921 pa->state.rot[0] = 1.0; 03922 pa->state.rot[1] = pa->state.rot[2] = pa->state.rot[3] = 0.0; 03923 03924 pa->time = 1.f; 03925 pa->dietime = sim->scene->r.efra + 1; 03926 pa->lifetime = sim->scene->r.efra; 03927 pa->alive = PARS_ALIVE; 03928 //if(a<25) fprintf(stderr,"FSPARTICLE debug set %s , a%d = %f,%f,%f , life=%f \n", filename, a, pa->co[0],pa->co[1],pa->co[2], pa->lifetime ); 03929 } else { 03930 // skip... 03931 for(j=0; j<2*3+1; j++) { 03932 float wrf; gzread(gzf, &wrf, sizeof( wrf )); 03933 } 03934 } 03935 fileParts++; 03936 } 03937 gzclose( gzf ); 03938 03939 totpart = psys->totpart = activeParts; 03940 snprintf(debugStrBuffer,256,"readFsPartData::done - particles:%d, active:%d, file:%d, mask:%d \n", psys->totpart,activeParts,fileParts,readMask); 03941 // bad level call 03942 // XXX elbeemDebugOut(debugStrBuffer); 03943 03944 } // fluid sim particles done 03945 } 03946 #endif // DISABLE_ELBEEM 03947 } 03948 03949 static int emit_particles(ParticleSimulationData *sim, PTCacheID *pid, float UNUSED(cfra)) 03950 { 03951 ParticleSystem *psys = sim->psys; 03952 int oldtotpart = psys->totpart; 03953 int totpart = tot_particles(psys, pid); 03954 03955 if(totpart != oldtotpart) 03956 realloc_particles(sim, totpart); 03957 03958 return totpart - oldtotpart; 03959 } 03960 /* Calculates the next state for all particles of the system 03961 * In particles code most fra-ending are frames, time-ending are fra*timestep (seconds) 03962 * 1. Emit particles 03963 * 2. Check cache (if used) and return if frame is cached 03964 * 3. Do dynamics 03965 * 4. Save to cache */ 03966 static void system_step(ParticleSimulationData *sim, float cfra) 03967 { 03968 ParticleSystem *psys = sim->psys; 03969 ParticleSettings *part = psys->part; 03970 PointCache *cache = psys->pointcache; 03971 PTCacheID ptcacheid, *pid = NULL; 03972 PARTICLE_P; 03973 float disp, cache_cfra = cfra; /*, *vg_vel= 0, *vg_tan= 0, *vg_rot= 0, *vg_size= 0; */ 03974 int startframe = 0, endframe = 100, oldtotpart = 0; 03975 03976 /* cache shouldn't be used for hair or "continue physics" */ 03977 if(part->type != PART_HAIR && BKE_ptcache_get_continue_physics() == 0) { 03978 psys_clear_temp_pointcache(psys); 03979 03980 /* set suitable cache range automatically */ 03981 if((cache->flag & (PTCACHE_BAKING|PTCACHE_BAKED))==0) 03982 psys_get_pointcache_start_end(sim->scene, psys, &cache->startframe, &cache->endframe); 03983 03984 pid = &ptcacheid; 03985 BKE_ptcache_id_from_particles(pid, sim->ob, psys); 03986 03987 BKE_ptcache_id_time(pid, sim->scene, 0.0f, &startframe, &endframe, NULL); 03988 03989 /* clear everythin on start frame */ 03990 if(cfra == startframe) { 03991 BKE_ptcache_id_reset(sim->scene, pid, PTCACHE_RESET_OUTDATED); 03992 BKE_ptcache_validate(cache, startframe); 03993 cache->flag &= ~PTCACHE_REDO_NEEDED; 03994 } 03995 03996 CLAMP(cache_cfra, startframe, endframe); 03997 } 03998 03999 /* 1. emit particles and redo particles if needed */ 04000 oldtotpart = psys->totpart; 04001 if(emit_particles(sim, pid, cfra) || psys->recalc & PSYS_RECALC_RESET) { 04002 distribute_particles(sim, part->from); 04003 initialize_all_particles(sim); 04004 /* reset only just created particles (on startframe all particles are recreated) */ 04005 reset_all_particles(sim, 0.0, cfra, oldtotpart); 04006 04007 if (psys->fluid_springs) { 04008 MEM_freeN(psys->fluid_springs); 04009 psys->fluid_springs = NULL; 04010 } 04011 04012 psys->tot_fluidsprings = psys->alloc_fluidsprings = 0; 04013 04014 /* flag for possible explode modifiers after this system */ 04015 sim->psmd->flag |= eParticleSystemFlag_Pars; 04016 04017 BKE_ptcache_id_clear(pid, PTCACHE_CLEAR_AFTER, cfra); 04018 } 04019 04020 /* 2. try to read from the cache */ 04021 if(pid) { 04022 int cache_result = BKE_ptcache_read(pid, cache_cfra); 04023 04024 if(ELEM(cache_result, PTCACHE_READ_EXACT, PTCACHE_READ_INTERPOLATED)) { 04025 cached_step(sim, cfra); 04026 update_children(sim); 04027 psys_update_path_cache(sim, cfra); 04028 04029 BKE_ptcache_validate(cache, (int)cache_cfra); 04030 04031 if(cache_result == PTCACHE_READ_INTERPOLATED && cache->flag & PTCACHE_REDO_NEEDED) 04032 BKE_ptcache_write(pid, (int)cache_cfra); 04033 04034 return; 04035 } 04036 /* Cache is supposed to be baked, but no data was found so bail out */ 04037 else if(cache->flag & PTCACHE_BAKED) { 04038 psys_reset(psys, PSYS_RESET_CACHE_MISS); 04039 return; 04040 } 04041 else if(cache_result == PTCACHE_READ_OLD) { 04042 psys->cfra = (float)cache->simframe; 04043 cached_step(sim, psys->cfra); 04044 } 04045 04046 /* if on second frame, write cache for first frame */ 04047 if(psys->cfra == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) 04048 BKE_ptcache_write(pid, startframe); 04049 } 04050 else 04051 BKE_ptcache_invalidate(cache); 04052 04053 /* 3. do dynamics */ 04054 /* set particles to be not calculated TODO: can't work with pointcache */ 04055 disp= (float)psys_get_current_display_percentage(psys)/100.0f; 04056 04057 LOOP_PARTICLES { 04058 if(PSYS_FRAND(p) > disp) 04059 pa->flag |= PARS_NO_DISP; 04060 else 04061 pa->flag &= ~PARS_NO_DISP; 04062 } 04063 04064 if(psys->totpart) { 04065 int dframe, subframe = 0, totframesback = 0, totsubframe = part->subframes+1; 04066 float fraction; 04067 04068 /* handle negative frame start at the first frame by doing 04069 * all the steps before the first frame */ 04070 if((int)cfra == startframe && part->sta < startframe) 04071 totframesback = (startframe - (int)part->sta); 04072 04073 for(dframe=-totframesback; dframe<=0; dframe++) { 04074 /* ok now we're all set so let's go */ 04075 for (subframe = 1; subframe <= totsubframe; subframe++) { 04076 fraction = (float)subframe/(float)totsubframe; 04077 dynamics_step(sim, cfra+dframe+fraction - 1.f); 04078 psys->cfra = cfra+dframe+fraction - 1.f; 04079 } 04080 } 04081 04082 } 04083 04084 /* 4. only write cache starting from second frame */ 04085 if(pid) { 04086 BKE_ptcache_validate(cache, (int)cache_cfra); 04087 if((int)cache_cfra != startframe) 04088 BKE_ptcache_write(pid, (int)cache_cfra); 04089 } 04090 04091 update_children(sim); 04092 04093 /* cleanup */ 04094 if(psys->lattice){ 04095 end_latt_deform(psys->lattice); 04096 psys->lattice= NULL; 04097 } 04098 } 04099 04100 /* system type has changed so set sensible defaults and clear non applicable flags */ 04101 static void psys_changed_type(ParticleSimulationData *sim) 04102 { 04103 ParticleSettings *part = sim->psys->part; 04104 PTCacheID pid; 04105 04106 BKE_ptcache_id_from_particles(&pid, sim->ob, sim->psys); 04107 04108 if(part->phystype != PART_PHYS_KEYED) 04109 sim->psys->flag &= ~PSYS_KEYED; 04110 04111 if(part->type == PART_HAIR) { 04112 if(ELEM4(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0) 04113 part->ren_as = PART_DRAW_PATH; 04114 04115 if(part->distr == PART_DISTR_GRID) 04116 part->distr = PART_DISTR_JIT; 04117 04118 if(ELEM3(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0) 04119 part->draw_as = PART_DRAW_REND; 04120 04121 CLAMP(part->path_start, 0.0f, 100.0f); 04122 CLAMP(part->path_end, 0.0f, 100.0f); 04123 04124 BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); 04125 } 04126 else { 04127 free_hair(sim->ob, sim->psys, 1); 04128 04129 CLAMP(part->path_start, 0.0f, MAX2(100.0f, part->end + part->lifetime)); 04130 CLAMP(part->path_end, 0.0f, MAX2(100.0f, part->end + part->lifetime)); 04131 } 04132 04133 psys_reset(sim->psys, PSYS_RESET_ALL); 04134 } 04135 void psys_check_boid_data(ParticleSystem *psys) 04136 { 04137 BoidParticle *bpa; 04138 PARTICLE_P; 04139 04140 pa = psys->particles; 04141 04142 if(!pa) 04143 return; 04144 04145 if(psys->part && psys->part->phystype==PART_PHYS_BOIDS) { 04146 if(!pa->boid) { 04147 bpa = MEM_callocN(psys->totpart * sizeof(BoidParticle), "Boid Data"); 04148 04149 LOOP_PARTICLES 04150 pa->boid = bpa++; 04151 } 04152 } 04153 else if(pa->boid){ 04154 MEM_freeN(pa->boid); 04155 LOOP_PARTICLES 04156 pa->boid = NULL; 04157 } 04158 } 04159 04160 static void fluid_default_settings(ParticleSettings *part){ 04161 SPHFluidSettings *fluid = part->fluid; 04162 04163 fluid->spring_k = 0.f; 04164 fluid->plasticity_constant = 0.1f; 04165 fluid->yield_ratio = 0.1f; 04166 fluid->rest_length = 1.f; 04167 fluid->viscosity_omega = 2.f; 04168 fluid->viscosity_beta = 0.1f; 04169 fluid->stiffness_k = 1.f; 04170 fluid->stiffness_knear = 1.f; 04171 fluid->rest_density = 1.f; 04172 fluid->buoyancy = 0.f; 04173 fluid->radius = 1.f; 04174 fluid->flag |= SPH_FAC_REPULSION|SPH_FAC_DENSITY|SPH_FAC_RADIUS|SPH_FAC_VISCOSITY|SPH_FAC_REST_LENGTH; 04175 } 04176 04177 static void psys_prepare_physics(ParticleSimulationData *sim) 04178 { 04179 ParticleSettings *part = sim->psys->part; 04180 04181 if(ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) { 04182 PTCacheID pid; 04183 BKE_ptcache_id_from_particles(&pid, sim->ob, sim->psys); 04184 BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0); 04185 } 04186 else { 04187 free_keyed_keys(sim->psys); 04188 sim->psys->flag &= ~PSYS_KEYED; 04189 } 04190 04191 if(part->phystype == PART_PHYS_BOIDS && part->boids == NULL) { 04192 BoidState *state; 04193 04194 part->boids = MEM_callocN(sizeof(BoidSettings), "Boid Settings"); 04195 boid_default_settings(part->boids); 04196 04197 state = boid_new_state(part->boids); 04198 BLI_addtail(&state->rules, boid_new_rule(eBoidRuleType_Separate)); 04199 BLI_addtail(&state->rules, boid_new_rule(eBoidRuleType_Flock)); 04200 04201 ((BoidRule*)state->rules.first)->flag |= BOIDRULE_CURRENT; 04202 04203 state->flag |= BOIDSTATE_CURRENT; 04204 BLI_addtail(&part->boids->states, state); 04205 } 04206 else if(part->phystype == PART_PHYS_FLUID && part->fluid == NULL) { 04207 part->fluid = MEM_callocN(sizeof(SPHFluidSettings), "SPH Fluid Settings"); 04208 fluid_default_settings(part); 04209 } 04210 04211 psys_check_boid_data(sim->psys); 04212 } 04213 static int hair_needs_recalc(ParticleSystem *psys) 04214 { 04215 if(!(psys->flag & PSYS_EDITED) && (!psys->edit || !psys->edit->edited) && 04216 ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_RESET || (psys->part->flag & PART_HAIR_REGROW && !psys->edit))) { 04217 return 1; 04218 } 04219 04220 return 0; 04221 } 04222 04223 /* main particle update call, checks that things are ok on the large scale and 04224 * then advances in to actual particle calculations depending on particle type */ 04225 void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys) 04226 { 04227 ParticleSimulationData sim= {0}; 04228 ParticleSettings *part = psys->part; 04229 float cfra; 04230 04231 /* drawdata is outdated after ANY change */ 04232 if(psys->pdd) psys->pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED; 04233 04234 if(!psys_check_enabled(ob, psys)) 04235 return; 04236 04237 cfra= BKE_curframe(scene); 04238 04239 sim.scene= scene; 04240 sim.ob= ob; 04241 sim.psys= psys; 04242 sim.psmd= psys_get_modifier(ob, psys); 04243 04244 /* system was already updated from modifier stack */ 04245 if(sim.psmd->flag & eParticleSystemFlag_psys_updated) { 04246 sim.psmd->flag &= ~eParticleSystemFlag_psys_updated; 04247 /* make sure it really was updated to cfra */ 04248 if(psys->cfra == cfra) 04249 return; 04250 } 04251 04252 if(!sim.psmd->dm) 04253 return; 04254 04255 /* execute drivers only, as animation has already been done */ 04256 BKE_animsys_evaluate_animdata(&part->id, part->adt, cfra, ADT_RECALC_DRIVERS); 04257 04258 if(psys->recalc & PSYS_RECALC_TYPE) 04259 psys_changed_type(&sim); 04260 04261 if(psys->recalc & PSYS_RECALC_RESET) 04262 psys->totunexist = 0; 04263 04264 /* setup necessary physics type dependent additional data if it doesn't yet exist */ 04265 psys_prepare_physics(&sim); 04266 04267 switch(part->type) { 04268 case PART_HAIR: 04269 { 04270 /* nothing to do so bail out early */ 04271 if(psys->totpart == 0 && part->totpart == 0) { 04272 psys_free_path_cache(psys, NULL); 04273 free_hair(ob, psys, 0); 04274 } 04275 /* (re-)create hair */ 04276 else if(hair_needs_recalc(psys)) { 04277 float hcfra=0.0f; 04278 int i, recalc = psys->recalc; 04279 04280 free_hair(ob, psys, 0); 04281 04282 if(psys->edit && psys->free_edit) { 04283 psys->free_edit(psys->edit); 04284 psys->edit = NULL; 04285 psys->free_edit = NULL; 04286 } 04287 04288 /* first step is negative so particles get killed and reset */ 04289 psys->cfra= 1.0f; 04290 04291 for(i=0; i<=part->hair_step; i++){ 04292 hcfra=100.0f*(float)i/(float)psys->part->hair_step; 04293 if((part->flag & PART_HAIR_REGROW)==0) 04294 BKE_animsys_evaluate_animdata(&part->id, part->adt, hcfra, ADT_RECALC_ANIM); 04295 system_step(&sim, hcfra); 04296 psys->cfra = hcfra; 04297 psys->recalc = 0; 04298 save_hair(&sim, hcfra); 04299 } 04300 04301 psys->flag |= PSYS_HAIR_DONE; 04302 psys->recalc = recalc; 04303 } 04304 else if(psys->flag & PSYS_EDITED) 04305 psys->flag |= PSYS_HAIR_DONE; 04306 04307 if(psys->flag & PSYS_HAIR_DONE) 04308 hair_step(&sim, cfra); 04309 break; 04310 } 04311 case PART_FLUID: 04312 { 04313 particles_fluid_step(&sim, (int)cfra); 04314 break; 04315 } 04316 default: 04317 { 04318 switch(part->phystype) { 04319 case PART_PHYS_NO: 04320 case PART_PHYS_KEYED: 04321 { 04322 PARTICLE_P; 04323 float disp = (float)psys_get_current_display_percentage(psys)/100.0f; 04324 04325 /* Particles without dynamics haven't been reset yet because they don't use pointcache */ 04326 if(psys->recalc & PSYS_RECALC_RESET) 04327 psys_reset(psys, PSYS_RESET_ALL); 04328 04329 if(emit_particles(&sim, NULL, cfra) || (psys->recalc & PSYS_RECALC_RESET)) { 04330 free_keyed_keys(psys); 04331 distribute_particles(&sim, part->from); 04332 initialize_all_particles(&sim); 04333 04334 /* flag for possible explode modifiers after this system */ 04335 sim.psmd->flag |= eParticleSystemFlag_Pars; 04336 } 04337 04338 LOOP_EXISTING_PARTICLES { 04339 pa->size = part->size; 04340 if(part->randsize > 0.0f) 04341 pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); 04342 04343 reset_particle(&sim, pa, 0.0, cfra); 04344 04345 if(PSYS_FRAND(p) > disp) 04346 pa->flag |= PARS_NO_DISP; 04347 else 04348 pa->flag &= ~PARS_NO_DISP; 04349 } 04350 04351 if(part->phystype == PART_PHYS_KEYED) { 04352 psys_count_keyed_targets(&sim); 04353 set_keyed_keys(&sim); 04354 psys_update_path_cache(&sim,(int)cfra); 04355 } 04356 break; 04357 } 04358 default: 04359 { 04360 /* the main dynamic particle system step */ 04361 system_step(&sim, cfra); 04362 break; 04363 } 04364 } 04365 break; 04366 } 04367 } 04368 04369 if(psys->cfra < cfra) { 04370 /* make sure emitter is left at correct time (particle emission can change this) */ 04371 while(ob) { 04372 BKE_animsys_evaluate_animdata(&ob->id, ob->adt, cfra, ADT_RECALC_ANIM); 04373 ob = ob->parent; 04374 } 04375 ob = sim.ob; 04376 where_is_object_time(scene, ob, cfra); 04377 } 04378 04379 psys->cfra = cfra; 04380 psys->recalc = 0; 04381 04382 /* save matrix for duplicators, at rendertime the actual dupliobject's matrix is used so don't update! */ 04383 if(psys->renderdata==0) 04384 invert_m4_m4(psys->imat, ob->obmat); 04385 } 04386