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