Blender V2.61 - r43446

particle.c

Go to the documentation of this file.
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): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <stdlib.h>
00034 #include <math.h>
00035 #include <string.h>
00036 
00037 #include "MEM_guardedalloc.h"
00038 
00039 #include "DNA_curve_types.h"
00040 #include "DNA_group_types.h"
00041 #include "DNA_key_types.h"
00042 #include "DNA_material_types.h"
00043 #include "DNA_mesh_types.h"
00044 #include "DNA_meshdata_types.h"
00045 #include "DNA_particle_types.h"
00046 #include "DNA_smoke_types.h"
00047 #include "DNA_scene_types.h"
00048 #include "DNA_dynamicpaint_types.h"
00049 
00050 #include "BLI_blenlib.h"
00051 #include "BLI_math.h"
00052 #include "BLI_utildefines.h"
00053 #include "BLI_kdtree.h"
00054 #include "BLI_rand.h"
00055 #include "BLI_threads.h"
00056 #include "BLI_linklist.h"
00057 #include "BLI_bpath.h"
00058 
00059 #include "BKE_anim.h"
00060 #include "BKE_animsys.h"
00061 
00062 #include "BKE_boids.h"
00063 #include "BKE_cloth.h"
00064 #include "BKE_effect.h"
00065 #include "BKE_global.h"
00066 #include "BKE_group.h"
00067 #include "BKE_main.h"
00068 #include "BKE_lattice.h"
00069 
00070 #include "BKE_displist.h"
00071 #include "BKE_particle.h"
00072 #include "BKE_object.h"
00073 #include "BKE_material.h"
00074 #include "BKE_key.h"
00075 #include "BKE_library.h"
00076 #include "BKE_depsgraph.h"
00077 #include "BKE_modifier.h"
00078 #include "BKE_mesh.h"
00079 #include "BKE_cdderivedmesh.h"
00080 #include "BKE_pointcache.h"
00081 #include "BKE_scene.h"
00082 #include "BKE_deform.h"
00083 
00084 #include "RE_render_ext.h"
00085 
00086 static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx,
00087                 ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex);
00088 static void do_child_modifiers(ParticleSimulationData *sim,
00089                 ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa,
00090                 float *orco, float mat[4][4], ParticleKey *state, float t);
00091 
00092 /* few helpers for countall etc. */
00093 int count_particles(ParticleSystem *psys)
00094 {
00095     ParticleSettings *part=psys->part;
00096     PARTICLE_P;
00097     int tot=0;
00098 
00099     LOOP_SHOWN_PARTICLES {
00100         if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0);
00101         else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0);
00102         else tot++;
00103     }
00104     return tot;
00105 }
00106 int count_particles_mod(ParticleSystem *psys, int totgr, int cur)
00107 {
00108     ParticleSettings *part=psys->part;
00109     PARTICLE_P;
00110     int tot=0;
00111 
00112     LOOP_SHOWN_PARTICLES {
00113         if(pa->alive == PARS_UNBORN && (part->flag & PART_UNBORN)==0);
00114         else if(pa->alive == PARS_DEAD && (part->flag & PART_DIED)==0);
00115         else if(p%totgr==cur) tot++;
00116     }
00117     return tot;
00118 }
00119 /* we allocate path cache memory in chunks instead of a big continguous
00120  * chunk, windows' memory allocater fails to find big blocks of memory often */
00121 
00122 #define PATH_CACHE_BUF_SIZE 1024
00123 
00124 static ParticleCacheKey **psys_alloc_path_cache_buffers(ListBase *bufs, int tot, int steps)
00125 {
00126     LinkData *buf;
00127     ParticleCacheKey **cache;
00128     int i, totkey, totbufkey;
00129 
00130     tot= MAX2(tot, 1);
00131     totkey = 0;
00132     cache = MEM_callocN(tot*sizeof(void*), "PathCacheArray");
00133 
00134     while(totkey < tot) {
00135         totbufkey= MIN2(tot-totkey, PATH_CACHE_BUF_SIZE);
00136         buf= MEM_callocN(sizeof(LinkData), "PathCacheLinkData");
00137         buf->data= MEM_callocN(sizeof(ParticleCacheKey)*totbufkey*steps, "ParticleCacheKey");
00138 
00139         for(i=0; i<totbufkey; i++)
00140             cache[totkey+i] = ((ParticleCacheKey*)buf->data) + i*steps;
00141 
00142         totkey += totbufkey;
00143         BLI_addtail(bufs, buf);
00144     }
00145 
00146     return cache;
00147 }
00148 
00149 static void psys_free_path_cache_buffers(ParticleCacheKey **cache, ListBase *bufs)
00150 {
00151     LinkData *buf;
00152 
00153     if(cache)
00154         MEM_freeN(cache);
00155 
00156     for(buf= bufs->first; buf; buf=buf->next)
00157         MEM_freeN(buf->data);
00158     BLI_freelistN(bufs);
00159 }
00160 
00161 /************************************************/
00162 /*          Getting stuff                       */
00163 /************************************************/
00164 /* get object's active particle system safely */
00165 ParticleSystem *psys_get_current(Object *ob)
00166 {
00167     ParticleSystem *psys;
00168     if(ob==NULL) return NULL;
00169 
00170     for(psys=ob->particlesystem.first; psys; psys=psys->next){
00171         if(psys->flag & PSYS_CURRENT)
00172             return psys;
00173     }
00174     
00175     return NULL;
00176 }
00177 short psys_get_current_num(Object *ob)
00178 {
00179     ParticleSystem *psys;
00180     short i;
00181 
00182     if(ob==NULL) return 0;
00183 
00184     for(psys=ob->particlesystem.first, i=0; psys; psys=psys->next, i++)
00185         if(psys->flag & PSYS_CURRENT)
00186             return i;
00187     
00188     return i;
00189 }
00190 void psys_set_current_num(Object *ob, int index)
00191 {
00192     ParticleSystem *psys;
00193     short i;
00194 
00195     if(ob==NULL) return;
00196 
00197     for(psys=ob->particlesystem.first, i=0; psys; psys=psys->next, i++) {
00198         if(i == index)
00199             psys->flag |= PSYS_CURRENT;
00200         else
00201             psys->flag &= ~PSYS_CURRENT;
00202     }
00203 }
00204 Object *psys_find_object(Scene *scene, ParticleSystem *psys)
00205 {
00206     Base *base;
00207     ParticleSystem *tpsys;
00208 
00209     for(base = scene->base.first; base; base = base->next) {
00210         for(tpsys = base->object->particlesystem.first; psys; psys=psys->next) {
00211             if(tpsys == psys)
00212                 return base->object;
00213         }
00214     }
00215 
00216     return NULL;
00217 }
00218 Object *psys_get_lattice(ParticleSimulationData *sim)
00219 {
00220     Object *lattice=NULL;
00221     
00222     if(psys_in_edit_mode(sim->scene, sim->psys)==0){
00223 
00224         ModifierData *md = (ModifierData*)psys_get_modifier(sim->ob, sim->psys);
00225 
00226         for(; md; md=md->next){
00227             if(md->type==eModifierType_Lattice){
00228                 LatticeModifierData *lmd = (LatticeModifierData *)md;
00229                 lattice=lmd->object;
00230                 break;
00231             }
00232         }
00233         if(lattice)
00234             init_latt_deform(lattice, NULL);
00235     }
00236 
00237     return lattice;
00238 }
00239 void psys_disable_all(Object *ob)
00240 {
00241     ParticleSystem *psys=ob->particlesystem.first;
00242 
00243     for(; psys; psys=psys->next)
00244         psys->flag |= PSYS_DISABLED;
00245 }
00246 void psys_enable_all(Object *ob)
00247 {
00248     ParticleSystem *psys=ob->particlesystem.first;
00249 
00250     for(; psys; psys=psys->next)
00251         psys->flag &= ~PSYS_DISABLED;
00252 }
00253 int psys_in_edit_mode(Scene *scene, ParticleSystem *psys)
00254 {
00255     return (scene->basact && (scene->basact->object->mode & OB_MODE_PARTICLE_EDIT) && psys==psys_get_current((scene->basact)->object) && (psys->edit || psys->pointcache->edit) && !psys->renderdata);
00256 }
00257 static void psys_create_frand(ParticleSystem *psys)
00258 {
00259     int i;
00260     float *rand = psys->frand = MEM_callocN(PSYS_FRAND_COUNT * sizeof(float), "particle randoms");
00261 
00262     BLI_srandom(psys->seed);
00263 
00264     for(i=0; i<1024; i++, rand++)
00265         *rand = BLI_frand();
00266 }
00267 int psys_check_enabled(Object *ob, ParticleSystem *psys)
00268 {
00269     ParticleSystemModifierData *psmd;
00270 
00271     if(psys->flag & PSYS_DISABLED || psys->flag & PSYS_DELETE || !psys->part)
00272         return 0;
00273 
00274     psmd= psys_get_modifier(ob, psys);
00275     if(psys->renderdata || G.rendering) {
00276         if(!(psmd->modifier.mode & eModifierMode_Render))
00277             return 0;
00278     }
00279     else if(!(psmd->modifier.mode & eModifierMode_Realtime))
00280         return 0;
00281 
00282     /* perhaps not the perfect place, but we have to be sure the rands are there before usage */
00283     if(!psys->frand)
00284         psys_create_frand(psys);
00285     else if(psys->recalc & PSYS_RECALC_RESET) {
00286         MEM_freeN(psys->frand);
00287         psys_create_frand(psys);
00288     }
00289     
00290     return 1;
00291 }
00292 
00293 int psys_check_edited(ParticleSystem *psys)
00294 {
00295     if(psys->part && psys->part->type==PART_HAIR)
00296         return (psys->flag & PSYS_EDITED || (psys->edit && psys->edit->edited));
00297     else
00298         return (psys->pointcache->edit && psys->pointcache->edit->edited);
00299 }
00300 
00301 void psys_check_group_weights(ParticleSettings *part)
00302 {
00303     ParticleDupliWeight *dw, *tdw;
00304     GroupObject *go;
00305     int current = 0;
00306 
00307     if(part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first) {
00308         /* first remove all weights that don't have an object in the group */
00309         dw = part->dupliweights.first;
00310         while(dw) {
00311             if(!object_in_group(dw->ob, part->dup_group)) {
00312                 tdw = dw->next;
00313                 BLI_freelinkN(&part->dupliweights, dw);
00314                 dw = tdw;
00315             }
00316             else
00317                 dw = dw->next;
00318         }
00319 
00320         /* then add objects in the group to new list */
00321         go = part->dup_group->gobject.first;
00322         while(go) {
00323             dw = part->dupliweights.first;
00324             while(dw && dw->ob != go->ob)
00325                 dw = dw->next;
00326             
00327             if(!dw) {
00328                 dw = MEM_callocN(sizeof(ParticleDupliWeight), "ParticleDupliWeight");
00329                 dw->ob = go->ob;
00330                 dw->count = 1;
00331                 BLI_addtail(&part->dupliweights, dw);
00332             }
00333 
00334             go = go->next;  
00335         }
00336 
00337         dw = part->dupliweights.first;
00338         for(; dw; dw=dw->next) {
00339             if(dw->flag & PART_DUPLIW_CURRENT) {
00340                 current = 1;
00341                 break;
00342             }
00343         }
00344 
00345         if(!current) {
00346             dw = part->dupliweights.first;
00347             if(dw)
00348                 dw->flag |= PART_DUPLIW_CURRENT;
00349         }
00350     }
00351     else {
00352         BLI_freelistN(&part->dupliweights);
00353     }
00354 }
00355 int psys_uses_gravity(ParticleSimulationData *sim)
00356 {
00357     return sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY && sim->psys->part && sim->psys->part->effector_weights->global_gravity != 0.0f;
00358 }
00359 /************************************************/
00360 /*          Freeing stuff                       */
00361 /************************************************/
00362 static void fluid_free_settings(SPHFluidSettings *fluid)
00363 {
00364     if(fluid)
00365         MEM_freeN(fluid); 
00366 }
00367 
00368 void psys_free_settings(ParticleSettings *part)
00369 {
00370     MTex *mtex;
00371     int a;
00372     BKE_free_animdata(&part->id);
00373     free_partdeflect(part->pd);
00374     free_partdeflect(part->pd2);
00375 
00376     if(part->effector_weights)
00377         MEM_freeN(part->effector_weights);
00378 
00379     BLI_freelistN(&part->dupliweights);
00380 
00381     boid_free_settings(part->boids);
00382     fluid_free_settings(part->fluid);
00383 
00384     for(a=0; a<MAX_MTEX; a++) {
00385         mtex= part->mtex[a];
00386         if(mtex && mtex->tex) mtex->tex->id.us--;
00387         if(mtex) MEM_freeN(mtex);
00388     }
00389 }
00390 
00391 void free_hair(Object *UNUSED(ob), ParticleSystem *psys, int dynamics)
00392 {
00393     PARTICLE_P;
00394 
00395     LOOP_PARTICLES {
00396         if(pa->hair)
00397             MEM_freeN(pa->hair);
00398         pa->hair = NULL;
00399         pa->totkey = 0;
00400     }
00401 
00402     psys->flag &= ~PSYS_HAIR_DONE;
00403 
00404     if(psys->clmd) {
00405         if(dynamics) {
00406             BKE_ptcache_free_list(&psys->ptcaches);
00407             psys->clmd->point_cache = psys->pointcache = NULL;
00408             psys->clmd->ptcaches.first = psys->clmd->ptcaches.last = NULL;
00409 
00410             modifier_free((ModifierData*)psys->clmd);
00411             
00412             psys->clmd = NULL;
00413             psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
00414         }
00415         else {
00416             cloth_free_modifier(psys->clmd);
00417         }
00418     }
00419 
00420     if(psys->hair_in_dm)
00421         psys->hair_in_dm->release(psys->hair_in_dm);
00422     psys->hair_in_dm = NULL;
00423 
00424     if(psys->hair_out_dm)
00425         psys->hair_out_dm->release(psys->hair_out_dm);
00426     psys->hair_out_dm = NULL;
00427 }
00428 void free_keyed_keys(ParticleSystem *psys)
00429 {
00430     PARTICLE_P;
00431 
00432     if(psys->part->type == PART_HAIR)
00433         return;
00434 
00435     if(psys->particles && psys->particles->keys) {
00436         MEM_freeN(psys->particles->keys);
00437 
00438         LOOP_PARTICLES {
00439             if(pa->keys) {
00440                 pa->keys= NULL;
00441                 pa->totkey= 0;
00442             }
00443         }
00444     }
00445 }
00446 static void free_child_path_cache(ParticleSystem *psys)
00447 {
00448     psys_free_path_cache_buffers(psys->childcache, &psys->childcachebufs);
00449     psys->childcache = NULL;
00450     psys->totchildcache = 0;
00451 }
00452 void psys_free_path_cache(ParticleSystem *psys, PTCacheEdit *edit)
00453 {
00454     if(edit) {
00455         psys_free_path_cache_buffers(edit->pathcache, &edit->pathcachebufs);
00456         edit->pathcache= NULL;
00457         edit->totcached= 0;
00458     }
00459     if(psys) {
00460         psys_free_path_cache_buffers(psys->pathcache, &psys->pathcachebufs);
00461         psys->pathcache= NULL;
00462         psys->totcached= 0;
00463 
00464         free_child_path_cache(psys);
00465     }
00466 }
00467 void psys_free_children(ParticleSystem *psys)
00468 {
00469     if(psys->child) {
00470         MEM_freeN(psys->child);
00471         psys->child= NULL;
00472         psys->totchild=0;
00473     }
00474 
00475     free_child_path_cache(psys);
00476 }
00477 void psys_free_particles(ParticleSystem *psys)
00478 {
00479     PARTICLE_P;
00480 
00481     if(psys->particles) {
00482         if(psys->part->type==PART_HAIR) {
00483             LOOP_PARTICLES {
00484                 if(pa->hair)
00485                     MEM_freeN(pa->hair);
00486             }
00487         }
00488         
00489         if(psys->particles->keys)
00490             MEM_freeN(psys->particles->keys);
00491         
00492         if(psys->particles->boid)
00493             MEM_freeN(psys->particles->boid);
00494 
00495         MEM_freeN(psys->particles);
00496         psys->particles= NULL;
00497         psys->totpart= 0;
00498     }
00499 }
00500 void psys_free_pdd(ParticleSystem *psys)
00501 {
00502     if(psys->pdd) {
00503         if(psys->pdd->cdata)
00504             MEM_freeN(psys->pdd->cdata);
00505         psys->pdd->cdata = NULL;
00506 
00507         if(psys->pdd->vdata)
00508             MEM_freeN(psys->pdd->vdata);
00509         psys->pdd->vdata = NULL;
00510 
00511         if(psys->pdd->ndata)
00512             MEM_freeN(psys->pdd->ndata);
00513         psys->pdd->ndata = NULL;
00514 
00515         if(psys->pdd->vedata)
00516             MEM_freeN(psys->pdd->vedata);
00517         psys->pdd->vedata = NULL;
00518 
00519         psys->pdd->totpoint = 0;
00520         psys->pdd->tot_vec_size = 0;
00521     }
00522 }
00523 /* free everything */
00524 void psys_free(Object *ob, ParticleSystem * psys)
00525 {   
00526     if(psys){
00527         int nr = 0;
00528         ParticleSystem * tpsys;
00529         
00530         psys_free_path_cache(psys, NULL);
00531 
00532         free_hair(ob, psys, 1);
00533 
00534         psys_free_particles(psys);
00535 
00536         if(psys->edit && psys->free_edit)
00537             psys->free_edit(psys->edit);
00538 
00539         if(psys->child){
00540             MEM_freeN(psys->child);
00541             psys->child = NULL;
00542             psys->totchild = 0;
00543         }
00544         
00545         // check if we are last non-visible particle system
00546         for(tpsys=ob->particlesystem.first; tpsys; tpsys=tpsys->next){
00547             if(tpsys->part)
00548             {
00549                 if(ELEM(tpsys->part->ren_as,PART_DRAW_OB,PART_DRAW_GR))
00550                 {
00551                     nr++;
00552                     break;
00553                 }
00554             }
00555         }
00556         // clear do-not-draw-flag
00557         if(!nr)
00558             ob->transflag &= ~OB_DUPLIPARTS;
00559 
00560         if(psys->part){
00561             psys->part->id.us--;        
00562             psys->part=NULL;
00563         }
00564 
00565         BKE_ptcache_free_list(&psys->ptcaches);
00566         psys->pointcache = NULL;
00567         
00568         BLI_freelistN(&psys->targets);
00569 
00570         BLI_bvhtree_free(psys->bvhtree);
00571         BLI_kdtree_free(psys->tree);
00572  
00573         if(psys->fluid_springs)
00574             MEM_freeN(psys->fluid_springs);
00575 
00576         pdEndEffectors(&psys->effectors);
00577 
00578         if(psys->frand)
00579             MEM_freeN(psys->frand);
00580 
00581         if(psys->pdd) {
00582             psys_free_pdd(psys);
00583             MEM_freeN(psys->pdd);
00584         }
00585 
00586         MEM_freeN(psys);
00587     }
00588 }
00589 
00590 /************************************************/
00591 /*          Rendering                           */
00592 /************************************************/
00593 /* these functions move away particle data and bring it back after
00594  * rendering, to make different render settings possible without
00595  * removing the previous data. this should be solved properly once */
00596 
00597 typedef struct ParticleRenderElem {
00598     int curchild, totchild, reduce;
00599     float lambda, t, scalemin, scalemax;
00600 } ParticleRenderElem;
00601 
00602 typedef struct ParticleRenderData {
00603     ChildParticle *child;
00604     ParticleCacheKey **pathcache;
00605     ParticleCacheKey **childcache;
00606     ListBase pathcachebufs, childcachebufs;
00607     int totchild, totcached, totchildcache;
00608     DerivedMesh *dm;
00609     int totdmvert, totdmedge, totdmface;
00610 
00611     float mat[4][4];
00612     float viewmat[4][4], winmat[4][4];
00613     int winx, winy;
00614 
00615     int dosimplify;
00616     int timeoffset;
00617     ParticleRenderElem *elems;
00618     int *origindex;
00619 } ParticleRenderData;
00620 
00621 static float psys_render_viewport_falloff(double rate, float dist, float width)
00622 {
00623     return pow(rate, dist/width);
00624 }
00625 
00626 static float psys_render_projected_area(ParticleSystem *psys, const float center[3], float area, double vprate, float *viewport)
00627 {
00628     ParticleRenderData *data= psys->renderdata;
00629     float co[4], view[3], ortho1[3], ortho2[3], w, dx, dy, radius;
00630     
00631     /* transform to view space */
00632     copy_v3_v3(co, center);
00633     co[3]= 1.0f;
00634     mul_m4_v4(data->viewmat, co);
00635     
00636     /* compute two vectors orthogonal to view vector */
00637     normalize_v3_v3(view, co);
00638     ortho_basis_v3v3_v3( ortho1, ortho2,view);
00639 
00640     /* compute on screen minification */
00641     w= co[2]*data->winmat[2][3] + data->winmat[3][3];
00642     dx= data->winx*ortho2[0]*data->winmat[0][0];
00643     dy= data->winy*ortho2[1]*data->winmat[1][1];
00644     w= sqrtf(dx*dx + dy*dy)/w;
00645 
00646     /* w squared because we are working with area */
00647     area= area*w*w;
00648 
00649     /* viewport of the screen test */
00650 
00651     /* project point on screen */
00652     mul_m4_v4(data->winmat, co);
00653     if(co[3] != 0.0f) {
00654         co[0]= 0.5f*data->winx*(1.0f + co[0]/co[3]);
00655         co[1]= 0.5f*data->winy*(1.0f + co[1]/co[3]);
00656     }
00657 
00658     /* screen space radius */
00659     radius= sqrt(area/(float)M_PI);
00660 
00661     /* make smaller using fallof once over screen edge */
00662     *viewport= 1.0f;
00663 
00664     if(co[0]+radius < 0.0f)
00665         *viewport *= psys_render_viewport_falloff(vprate, -(co[0]+radius), data->winx);
00666     else if(co[0]-radius > data->winx)
00667         *viewport *= psys_render_viewport_falloff(vprate, (co[0]-radius) - data->winx, data->winx);
00668 
00669     if(co[1]+radius < 0.0f)
00670         *viewport *= psys_render_viewport_falloff(vprate, -(co[1]+radius), data->winy);
00671     else if(co[1]-radius > data->winy)
00672         *viewport *= psys_render_viewport_falloff(vprate, (co[1]-radius) - data->winy, data->winy);
00673     
00674     return area;
00675 }
00676 
00677 void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[][4], float winmat[][4], int winx, int winy, int timeoffset)
00678 {
00679     ParticleRenderData*data;
00680     ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
00681 
00682     if(!G.rendering)
00683         return;
00684     if(psys->renderdata)
00685         return;
00686 
00687     data= MEM_callocN(sizeof(ParticleRenderData), "ParticleRenderData");
00688 
00689     data->child= psys->child;
00690     data->totchild= psys->totchild;
00691     data->pathcache= psys->pathcache;
00692     data->pathcachebufs.first = psys->pathcachebufs.first;
00693     data->pathcachebufs.last = psys->pathcachebufs.last;
00694     data->totcached= psys->totcached;
00695     data->childcache= psys->childcache;
00696     data->childcachebufs.first = psys->childcachebufs.first;
00697     data->childcachebufs.last = psys->childcachebufs.last;
00698     data->totchildcache= psys->totchildcache;
00699 
00700     if(psmd->dm)
00701         data->dm= CDDM_copy(psmd->dm);
00702     data->totdmvert= psmd->totdmvert;
00703     data->totdmedge= psmd->totdmedge;
00704     data->totdmface= psmd->totdmface;
00705 
00706     psys->child= NULL;
00707     psys->pathcache= NULL;
00708     psys->childcache= NULL;
00709     psys->totchild= psys->totcached= psys->totchildcache= 0;
00710     psys->pathcachebufs.first = psys->pathcachebufs.last = NULL;
00711     psys->childcachebufs.first = psys->childcachebufs.last = NULL;
00712 
00713     copy_m4_m4(data->winmat, winmat);
00714     mult_m4_m4m4(data->viewmat, viewmat, ob->obmat);
00715     mult_m4_m4m4(data->mat, winmat, data->viewmat);
00716     data->winx= winx;
00717     data->winy= winy;
00718 
00719     data->timeoffset= timeoffset;
00720 
00721     psys->renderdata= data;
00722 
00723     /* Hair can and has to be recalculated if everything isn't displayed. */
00724     if(psys->part->disp != 100 && psys->part->type == PART_HAIR)
00725         psys->recalc |= PSYS_RECALC_RESET;
00726 }
00727 
00728 void psys_render_restore(Object *ob, ParticleSystem *psys)
00729 {
00730     ParticleRenderData*data;
00731     ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
00732 
00733     data= psys->renderdata;
00734     if(!data)
00735         return;
00736     
00737     if(data->elems)
00738         MEM_freeN(data->elems);
00739 
00740     if(psmd->dm) {
00741         psmd->dm->needsFree= 1;
00742         psmd->dm->release(psmd->dm);
00743     }
00744 
00745     psys_free_path_cache(psys, NULL);
00746 
00747     if(psys->child){
00748         MEM_freeN(psys->child);
00749         psys->child= 0;
00750         psys->totchild= 0;
00751     }
00752 
00753     psys->child= data->child;
00754     psys->totchild= data->totchild;
00755     psys->pathcache= data->pathcache;
00756     psys->pathcachebufs.first = data->pathcachebufs.first;
00757     psys->pathcachebufs.last = data->pathcachebufs.last;
00758     psys->totcached= data->totcached;
00759     psys->childcache= data->childcache;
00760     psys->childcachebufs.first = data->childcachebufs.first;
00761     psys->childcachebufs.last = data->childcachebufs.last;
00762     psys->totchildcache= data->totchildcache;
00763 
00764     psmd->dm= data->dm;
00765     psmd->totdmvert= data->totdmvert;
00766     psmd->totdmedge= data->totdmedge;
00767     psmd->totdmface= data->totdmface;
00768     psmd->flag &= ~eParticleSystemFlag_psys_updated;
00769 
00770     if(psmd->dm)
00771         psys_calc_dmcache(ob, psmd->dm, psys);
00772 
00773     MEM_freeN(data);
00774     psys->renderdata= NULL;
00775 }
00776 
00777 int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
00778 {
00779     DerivedMesh *dm= ctx->dm;
00780     Mesh *me= (Mesh*)(ctx->sim.ob->data);
00781     MFace *mf, *mface;
00782     MVert *mvert;
00783     ParticleRenderData *data;
00784     ParticleRenderElem *elems, *elem;
00785     ParticleSettings *part= ctx->sim.psys->part;
00786     float *facearea, (*facecenter)[3], size[3], fac, powrate, scaleclamp;
00787     float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport;
00788     double vprate;
00789     int *origindex, *facetotvert;
00790     int a, b, totorigface, totface, newtot, skipped;
00791 
00792     if(part->ren_as!=PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND))
00793         return tot;
00794     if(!ctx->sim.psys->renderdata)
00795         return tot;
00796 
00797     data= ctx->sim.psys->renderdata;
00798     if(data->timeoffset)
00799         return 0;
00800     if(!(part->simplify_flag & PART_SIMPLIFY_ENABLE))
00801         return tot;
00802 
00803     mvert= dm->getVertArray(dm);
00804     mface= dm->getFaceArray(dm);
00805     origindex= dm->getFaceDataArray(dm, CD_ORIGINDEX);
00806     totface= dm->getNumFaces(dm);
00807     totorigface= me->totface;
00808 
00809     if(totface == 0 || totorigface == 0)
00810         return tot;
00811 
00812     facearea= MEM_callocN(sizeof(float)*totorigface, "SimplifyFaceArea");
00813     facecenter= MEM_callocN(sizeof(float[3])*totorigface, "SimplifyFaceCenter");
00814     facetotvert= MEM_callocN(sizeof(int)*totorigface, "SimplifyFaceArea");
00815     elems= MEM_callocN(sizeof(ParticleRenderElem)*totorigface, "SimplifyFaceElem");
00816 
00817     if(data->elems)
00818         MEM_freeN(data->elems);
00819 
00820     data->dosimplify= 1;
00821     data->elems= elems;
00822     data->origindex= origindex;
00823 
00824     /* compute number of children per original face */
00825     for(a=0; a<tot; a++) {
00826         b= (origindex)? origindex[ctx->index[a]]: ctx->index[a];
00827         if(b != -1)
00828             elems[b].totchild++;
00829     }
00830 
00831     /* compute areas and centers of original faces */
00832     for(mf=mface, a=0; a<totface; a++, mf++) {
00833         b= (origindex)? origindex[a]: a;
00834 
00835         if(b != -1) {
00836             copy_v3_v3(co1, mvert[mf->v1].co);
00837             copy_v3_v3(co2, mvert[mf->v2].co);
00838             copy_v3_v3(co3, mvert[mf->v3].co);
00839 
00840             add_v3_v3(facecenter[b], co1);
00841             add_v3_v3(facecenter[b], co2);
00842             add_v3_v3(facecenter[b], co3);
00843 
00844             if(mf->v4) {
00845                 copy_v3_v3(co4, mvert[mf->v4].co);
00846                 add_v3_v3(facecenter[b], co4);
00847                 facearea[b] += area_quad_v3(co1, co2, co3, co4);
00848                 facetotvert[b] += 4;
00849             }
00850             else {
00851                 facearea[b] += area_tri_v3(co1, co2, co3);
00852                 facetotvert[b] += 3;
00853             }
00854         }
00855     }
00856 
00857     for(a=0; a<totorigface; a++)
00858         if(facetotvert[a] > 0)
00859             mul_v3_fl(facecenter[a], 1.0f/facetotvert[a]);
00860 
00861     /* for conversion from BU area / pixel area to reference screen size */
00862     mesh_get_texspace(me, 0, 0, size);
00863     fac= ((size[0] + size[1] + size[2])/3.0f)/part->simplify_refsize;
00864     fac= fac*fac;
00865 
00866     powrate= log(0.5f)/log(part->simplify_rate*0.5f);
00867     if(part->simplify_flag & PART_SIMPLIFY_VIEWPORT)
00868         vprate= pow(1.0f - part->simplify_viewport, 5.0);
00869     else
00870         vprate= 1.0;
00871 
00872     /* set simplification parameters per original face */
00873     for(a=0, elem=elems; a<totorigface; a++, elem++) {
00874         area = psys_render_projected_area(ctx->sim.psys, facecenter[a], facearea[a], vprate, &viewport);
00875         arearatio= fac*area/facearea[a];
00876 
00877         if((arearatio < 1.0f || viewport < 1.0f) && elem->totchild) {
00878             /* lambda is percentage of elements to keep */
00879             lambda= (arearatio < 1.0f)? powf(arearatio, powrate): 1.0f;
00880             lambda *= viewport;
00881 
00882             lambda= MAX2(lambda, 1.0f/elem->totchild);
00883 
00884             /* compute transition region */
00885             t= part->simplify_transition;
00886             elem->t= (lambda-t < 0.0f)? lambda: (lambda+t > 1.0f)? 1.0f-lambda: t;
00887             elem->reduce= 1;
00888 
00889             /* scale at end and beginning of the transition region */
00890             elem->scalemax= (lambda+t < 1.0f)? 1.0f/lambda: 1.0f/(1.0f - elem->t*elem->t/t);
00891             elem->scalemin= (lambda+t < 1.0f)? 0.0f: elem->scalemax*(1.0f-elem->t/t);
00892 
00893             elem->scalemin= sqrt(elem->scalemin);
00894             elem->scalemax= sqrt(elem->scalemax);
00895 
00896             /* clamp scaling */
00897             scaleclamp= MIN2(elem->totchild, 10.0f);
00898             elem->scalemin= MIN2(scaleclamp, elem->scalemin);
00899             elem->scalemax= MIN2(scaleclamp, elem->scalemax);
00900 
00901             /* extend lambda to include transition */
00902             lambda= lambda + elem->t;
00903             if(lambda > 1.0f)
00904                 lambda= 1.0f;
00905         }
00906         else {
00907             lambda= arearatio;
00908 
00909             elem->scalemax= 1.0f; //sqrt(lambda);
00910             elem->scalemin= 1.0f; //sqrt(lambda);
00911             elem->reduce= 0;
00912         }
00913 
00914         elem->lambda= lambda;
00915         elem->scalemin= sqrt(elem->scalemin);
00916         elem->scalemax= sqrt(elem->scalemax);
00917         elem->curchild= 0;
00918     }
00919 
00920     MEM_freeN(facearea);
00921     MEM_freeN(facecenter);
00922     MEM_freeN(facetotvert);
00923 
00924     /* move indices and set random number skipping */
00925     ctx->skip= MEM_callocN(sizeof(int)*tot, "SimplificationSkip");
00926 
00927     skipped= 0;
00928     for(a=0, newtot=0; a<tot; a++) {
00929         b= (origindex)? origindex[ctx->index[a]]: ctx->index[a];
00930         if(b != -1) {
00931             if(elems[b].curchild++ < ceil(elems[b].lambda*elems[b].totchild)) {
00932                 ctx->index[newtot]= ctx->index[a];
00933                 ctx->skip[newtot]= skipped;
00934                 skipped= 0;
00935                 newtot++;
00936             }
00937             else skipped++;
00938         }
00939         else skipped++;
00940     }
00941 
00942     for(a=0, elem=elems; a<totorigface; a++, elem++)
00943         elem->curchild= 0;
00944 
00945     return newtot;
00946 }
00947 
00948 int psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float *params)
00949 {
00950     ParticleRenderData *data;
00951     ParticleRenderElem *elem;
00952     float x, w, scale, alpha, lambda, t, scalemin, scalemax;
00953     int b;
00954 
00955     if(!(psys->renderdata && (psys->part->simplify_flag & PART_SIMPLIFY_ENABLE)))
00956         return 0;
00957     
00958     data= psys->renderdata;
00959     if(!data->dosimplify)
00960         return 0;
00961     
00962     b= (data->origindex)? data->origindex[cpa->num]: cpa->num;
00963     if(b == -1)
00964         return 0;
00965 
00966     elem= &data->elems[b];
00967 
00968     lambda= elem->lambda;
00969     t= elem->t;
00970     scalemin= elem->scalemin;
00971     scalemax= elem->scalemax;
00972 
00973     if(!elem->reduce) {
00974         scale= scalemin;
00975         alpha= 1.0f;
00976     }
00977     else {
00978         x= (elem->curchild+0.5f)/elem->totchild;
00979         if(x < lambda-t) {
00980             scale= scalemax;
00981             alpha= 1.0f;
00982         }
00983         else if(x >= lambda+t) {
00984             scale= scalemin;
00985             alpha= 0.0f;
00986         }
00987         else {
00988             w= (lambda+t - x)/(2.0f*t);
00989             scale= scalemin + (scalemax - scalemin)*w;
00990             alpha= w;
00991         }
00992     }
00993 
00994     params[0]= scale;
00995     params[1]= alpha;
00996 
00997     elem->curchild++;
00998 
00999     return 1;
01000 }
01001 
01002 /************************************************/
01003 /*          Interpolation                       */
01004 /************************************************/
01005 static float interpolate_particle_value(float v1, float v2, float v3, float v4, const float w[4], int four)
01006 {
01007     float value;
01008 
01009     value= w[0]*v1 + w[1]*v2 + w[2]*v3;
01010     if(four)
01011         value += w[3]*v4;
01012 
01013     CLAMP(value, 0.f, 1.f);
01014     
01015     return value;
01016 }
01017 
01018 void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, ParticleKey *result, int velocity)
01019 {
01020     float t[4];
01021 
01022     if(type<0) {
01023         interp_cubic_v3( result->co, result->vel,keys[1].co, keys[1].vel, keys[2].co, keys[2].vel, dt);
01024     }
01025     else {
01026         key_curve_position_weights(dt, t, type);
01027 
01028         interp_v3_v3v3v3v3(result->co, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
01029 
01030         if(velocity){
01031             float temp[3];
01032 
01033             if(dt>0.999f){
01034                 key_curve_position_weights(dt-0.001f, t, type);
01035                 interp_v3_v3v3v3v3(temp, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
01036                 sub_v3_v3v3(result->vel, result->co, temp);
01037             }
01038             else{
01039                 key_curve_position_weights(dt+0.001f, t, type);
01040                 interp_v3_v3v3v3v3(temp, keys[0].co, keys[1].co, keys[2].co, keys[3].co, t);
01041                 sub_v3_v3v3(result->vel, temp, result->co);
01042             }
01043         }
01044     }
01045 }
01046 
01047 
01048 
01049 typedef struct ParticleInterpolationData {
01050     HairKey *hkey[2];
01051 
01052     DerivedMesh *dm;
01053     MVert *mvert[2];
01054 
01055     int keyed;
01056     ParticleKey *kkey[2];
01057 
01058     PointCache *cache;
01059     PTCacheMem *pm;
01060 
01061     PTCacheEditPoint *epoint;
01062     PTCacheEditKey *ekey[2];
01063 
01064     float birthtime, dietime;
01065     int bspline;
01066 } ParticleInterpolationData;
01067 /* Assumes pointcache->mem_cache exists, so for disk cached particles call psys_make_temp_pointcache() before use */
01068 /* It uses ParticleInterpolationData->pm to store the current memory cache frame so it's thread safe. */
01069 static void get_pointcache_keys_for_time(Object *UNUSED(ob), PointCache *cache, PTCacheMem **cur, int index, float t, ParticleKey *key1, ParticleKey *key2)
01070 {
01071     static PTCacheMem *pm = NULL;
01072     int index1, index2;
01073 
01074     if(index < 0) { /* initialize */
01075         *cur = cache->mem_cache.first;
01076 
01077         if(*cur)
01078             *cur = (*cur)->next;
01079     }
01080     else {
01081         if(*cur) {
01082             while(*cur && (*cur)->next && (float)(*cur)->frame < t)
01083                 *cur = (*cur)->next;
01084 
01085             pm = *cur;
01086 
01087             index2 = BKE_ptcache_mem_index_find(pm, index);
01088             index1 = BKE_ptcache_mem_index_find(pm->prev, index);
01089 
01090             BKE_ptcache_make_particle_key(key2, index2, pm->data, (float)pm->frame);
01091             if(index1 < 0)
01092                 copy_particle_key(key1, key2, 1);
01093             else
01094                 BKE_ptcache_make_particle_key(key1, index1, pm->prev->data, (float)pm->prev->frame);
01095         }
01096         else if(cache->mem_cache.first) {
01097             pm = cache->mem_cache.first;
01098             index2 = BKE_ptcache_mem_index_find(pm, index);
01099             BKE_ptcache_make_particle_key(key2, index2, pm->data, (float)pm->frame);
01100             copy_particle_key(key1, key2, 1);
01101         }
01102     }
01103 }
01104 static int get_pointcache_times_for_particle(PointCache *cache, int index, float *start, float *end)
01105 {
01106     PTCacheMem *pm;
01107     int ret = 0;
01108 
01109     for(pm=cache->mem_cache.first; pm; pm=pm->next) {
01110         if(BKE_ptcache_mem_index_find(pm, index) >= 0) {
01111             *start = pm->frame;
01112             ret++;
01113             break;
01114         }
01115     }
01116 
01117     for(pm=cache->mem_cache.last; pm; pm=pm->prev) {
01118         if(BKE_ptcache_mem_index_find(pm, index) >= 0) {
01119             *end = pm->frame;
01120             ret++;
01121             break;
01122         }
01123     }
01124 
01125     return ret == 2;
01126 }
01127 
01128 float psys_get_dietime_from_cache(PointCache *cache, int index)
01129 {
01130     PTCacheMem *pm;
01131     int dietime = 10000000; /* some max value so that we can default to pa->time+lifetime */
01132 
01133     for(pm=cache->mem_cache.last; pm; pm=pm->prev) {
01134         if(BKE_ptcache_mem_index_find(pm, index) >= 0)
01135             return (float)pm->frame;
01136     }
01137 
01138     return (float)dietime;
01139 }
01140 
01141 static void init_particle_interpolation(Object *ob, ParticleSystem *psys, ParticleData *pa, ParticleInterpolationData *pind)
01142 {
01143 
01144     if(pind->epoint) {
01145         PTCacheEditPoint *point = pind->epoint;
01146 
01147         pind->ekey[0] = point->keys;
01148         pind->ekey[1] = point->totkey > 1 ? point->keys + 1 : NULL;
01149 
01150         pind->birthtime = *(point->keys->time);
01151         pind->dietime = *((point->keys + point->totkey - 1)->time);
01152     }
01153     else if(pind->keyed) {
01154         ParticleKey *key = pa->keys;
01155         pind->kkey[0] = key;
01156         pind->kkey[1] = pa->totkey > 1 ? key + 1 : NULL;
01157 
01158         pind->birthtime = key->time;
01159         pind->dietime = (key + pa->totkey - 1)->time;
01160     }
01161     else if(pind->cache) {
01162         float start=0.0f, end=0.0f;
01163         get_pointcache_keys_for_time(ob, pind->cache, &pind->pm, -1, 0.0f, NULL, NULL);
01164         pind->birthtime = pa ? pa->time : pind->cache->startframe;
01165         pind->dietime = pa ? pa->dietime : pind->cache->endframe;
01166 
01167         if(get_pointcache_times_for_particle(pind->cache, pa - psys->particles, &start, &end)) {
01168             pind->birthtime = MAX2(pind->birthtime, start);
01169             pind->dietime = MIN2(pind->dietime, end);
01170         }
01171     }
01172     else {
01173         HairKey *key = pa->hair;
01174         pind->hkey[0] = key;
01175         pind->hkey[1] = key + 1;
01176 
01177         pind->birthtime = key->time;
01178         pind->dietime = (key + pa->totkey - 1)->time;
01179 
01180         if(pind->dm) {
01181             pind->mvert[0] = CDDM_get_vert(pind->dm, pa->hair_index);
01182             pind->mvert[1] = pind->mvert[0] + 1;
01183         }
01184     }
01185 }
01186 static void edit_to_particle(ParticleKey *key, PTCacheEditKey *ekey)
01187 {
01188     copy_v3_v3(key->co, ekey->co);
01189     if(ekey->vel) {
01190         copy_v3_v3(key->vel, ekey->vel);
01191     }
01192     key->time = *(ekey->time);
01193 }
01194 static void hair_to_particle(ParticleKey *key, HairKey *hkey)
01195 {
01196     copy_v3_v3(key->co, hkey->co);
01197     key->time = hkey->time;
01198 }
01199 
01200 static void mvert_to_particle(ParticleKey *key, MVert *mvert, HairKey *hkey)
01201 {
01202     copy_v3_v3(key->co, mvert->co);
01203     key->time = hkey->time;
01204 }
01205 
01206 static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData *pa, float t, ParticleInterpolationData *pind, ParticleKey *result)
01207 {
01208     PTCacheEditPoint *point = pind->epoint;
01209     ParticleKey keys[4];
01210     int point_vel = (point && point->keys->vel);
01211     float real_t, dfra, keytime, invdt = 1.f;
01212 
01213     /* billboards wont fill in all of these, so start cleared */
01214     memset(keys, 0, sizeof(keys));
01215 
01216     /* interpret timing and find keys */
01217     if(point) {
01218         if(result->time < 0.0f)
01219             real_t = -result->time;
01220         else
01221             real_t = *(pind->ekey[0]->time) + t * (*(pind->ekey[0][point->totkey-1].time) - *(pind->ekey[0]->time));
01222 
01223         while(*(pind->ekey[1]->time) < real_t)
01224             pind->ekey[1]++;
01225 
01226         pind->ekey[0] = pind->ekey[1] - 1;
01227     }
01228     else if(pind->keyed) {
01229         /* we have only one key, so let's use that */
01230         if(pind->kkey[1]==NULL) {
01231             copy_particle_key(result, pind->kkey[0], 1);
01232             return;
01233         }
01234 
01235         if(result->time < 0.0f)
01236             real_t = -result->time;
01237         else
01238             real_t = pind->kkey[0]->time + t * (pind->kkey[0][pa->totkey-1].time - pind->kkey[0]->time);
01239 
01240         if(psys->part->phystype==PART_PHYS_KEYED && psys->flag & PSYS_KEYED_TIMING) {
01241             ParticleTarget *pt = psys->targets.first;
01242 
01243             pt=pt->next;
01244 
01245             while(pt && pa->time + pt->time < real_t)
01246                 pt= pt->next;
01247 
01248             if(pt) {
01249                 pt=pt->prev;
01250 
01251                 if(pa->time + pt->time + pt->duration > real_t)
01252                     real_t = pa->time + pt->time;
01253             }
01254             else
01255                 real_t = pa->time + ((ParticleTarget*)psys->targets.last)->time;
01256         }
01257 
01258         CLAMP(real_t, pa->time, pa->dietime);
01259 
01260         while(pind->kkey[1]->time < real_t)
01261             pind->kkey[1]++;
01262         
01263         pind->kkey[0] = pind->kkey[1] - 1;
01264     }
01265     else if(pind->cache) {
01266         if(result->time < 0.0f) /* flag for time in frames */
01267             real_t = -result->time;
01268         else
01269             real_t = pa->time + t * (pa->dietime - pa->time);
01270     }
01271     else {
01272         if(result->time < 0.0f)
01273             real_t = -result->time;
01274         else
01275             real_t = pind->hkey[0]->time + t * (pind->hkey[0][pa->totkey-1].time - pind->hkey[0]->time);
01276 
01277         while(pind->hkey[1]->time < real_t) {
01278             pind->hkey[1]++;
01279             pind->mvert[1]++;
01280         }
01281 
01282         pind->hkey[0] = pind->hkey[1] - 1;
01283     }
01284 
01285     /* set actual interpolation keys */
01286     if(point) {
01287         edit_to_particle(keys + 1, pind->ekey[0]);
01288         edit_to_particle(keys + 2, pind->ekey[1]);
01289     }
01290     else if(pind->dm) {
01291         pind->mvert[0] = pind->mvert[1] - 1;
01292         mvert_to_particle(keys + 1, pind->mvert[0], pind->hkey[0]);
01293         mvert_to_particle(keys + 2, pind->mvert[1], pind->hkey[1]);
01294     }
01295     else if(pind->keyed) {
01296         memcpy(keys + 1, pind->kkey[0], sizeof(ParticleKey));
01297         memcpy(keys + 2, pind->kkey[1], sizeof(ParticleKey));
01298     }
01299     else if(pind->cache) {
01300         get_pointcache_keys_for_time(NULL, pind->cache, &pind->pm, p, real_t, keys+1, keys+2);
01301     }
01302     else {
01303         hair_to_particle(keys + 1, pind->hkey[0]);
01304         hair_to_particle(keys + 2, pind->hkey[1]);
01305     }
01306 
01307     /* set secondary interpolation keys for hair */
01308     if(!pind->keyed && !pind->cache && !point_vel) {
01309         if(point) {
01310             if(pind->ekey[0] != point->keys)
01311                 edit_to_particle(keys, pind->ekey[0] - 1);
01312             else
01313                 edit_to_particle(keys, pind->ekey[0]);
01314         }
01315         else if(pind->dm) {
01316             if(pind->hkey[0] != pa->hair)
01317                 mvert_to_particle(keys, pind->mvert[0] - 1, pind->hkey[0] - 1);
01318             else
01319                 mvert_to_particle(keys, pind->mvert[0], pind->hkey[0]);
01320         }
01321         else {
01322             if(pind->hkey[0] != pa->hair)
01323                 hair_to_particle(keys, pind->hkey[0] - 1);
01324             else
01325                 hair_to_particle(keys, pind->hkey[0]);
01326         }
01327 
01328         if(point) {
01329             if(pind->ekey[1] != point->keys + point->totkey - 1)
01330                 edit_to_particle(keys + 3, pind->ekey[1] + 1);
01331             else
01332                 edit_to_particle(keys + 3, pind->ekey[1]);
01333         }
01334         else if(pind->dm) {
01335             if(pind->hkey[1] != pa->hair + pa->totkey - 1)
01336                 mvert_to_particle(keys + 3, pind->mvert[1] + 1, pind->hkey[1] + 1);
01337             else
01338                 mvert_to_particle(keys + 3, pind->mvert[1], pind->hkey[1]);
01339         }
01340         else {
01341             if(pind->hkey[1] != pa->hair + pa->totkey - 1)
01342                 hair_to_particle(keys + 3, pind->hkey[1] + 1);
01343             else
01344                 hair_to_particle(keys + 3, pind->hkey[1]);
01345         }
01346     }
01347 
01348     dfra = keys[2].time - keys[1].time;
01349     keytime = (real_t - keys[1].time) / dfra;
01350 
01351     /* convert velocity to timestep size */
01352     if(pind->keyed || pind->cache || point_vel){
01353         invdt = dfra * 0.04f * (psys ? psys->part->timetweak : 1.f);
01354         mul_v3_fl(keys[1].vel, invdt);
01355         mul_v3_fl(keys[2].vel, invdt);
01356         interp_qt_qtqt(result->rot,keys[1].rot,keys[2].rot,keytime);
01357     }
01358 
01359     /* now we should have in chronologiacl order k1<=k2<=t<=k3<=k4 with keytime between [0,1]->[k2,k3] (k1 & k4 used for cardinal & bspline interpolation)*/
01360     psys_interpolate_particle((pind->keyed || pind->cache || point_vel) ? -1 /* signal for cubic interpolation */
01361         : (pind->bspline ? KEY_BSPLINE : KEY_CARDINAL)
01362         ,keys, keytime, result, 1);
01363 
01364     /* the velocity needs to be converted back from cubic interpolation */
01365     if(pind->keyed || pind->cache || point_vel)
01366         mul_v3_fl(result->vel, 1.f/invdt);
01367 }
01368 /************************************************/
01369 /*          Particles on a dm                   */
01370 /************************************************/
01371 /* interpolate a location on a face based on face coordinates */
01372 void psys_interpolate_face(MVert *mvert, MFace *mface, MTFace *tface, float (*orcodata)[3],
01373                            float *w, float *vec, float *nor, float *utan, float *vtan, float *orco,float *ornor)
01374 {
01375     float *v1=0, *v2=0, *v3=0, *v4=0;
01376     float e1[3],e2[3],s1,s2,t1,t2;
01377     float *uv1, *uv2, *uv3, *uv4;
01378     float n1[3], n2[3], n3[3], n4[3];
01379     float tuv[4][2];
01380     float *o1, *o2, *o3, *o4;
01381 
01382     v1= mvert[mface->v1].co;
01383     v2= mvert[mface->v2].co;
01384     v3= mvert[mface->v3].co;
01385 
01386     normal_short_to_float_v3(n1, mvert[mface->v1].no);
01387     normal_short_to_float_v3(n2, mvert[mface->v2].no);
01388     normal_short_to_float_v3(n3, mvert[mface->v3].no);
01389 
01390     if(mface->v4) {
01391         v4= mvert[mface->v4].co;
01392         normal_short_to_float_v3(n4, mvert[mface->v4].no);
01393         
01394         interp_v3_v3v3v3v3(vec, v1, v2, v3, v4, w);
01395 
01396         if(nor){
01397             if(mface->flag & ME_SMOOTH)
01398                 interp_v3_v3v3v3v3(nor, n1, n2, n3, n4, w);
01399             else
01400                 normal_quad_v3(nor,v1,v2,v3,v4);
01401         }
01402     }
01403     else {
01404         interp_v3_v3v3v3(vec, v1, v2, v3, w);
01405 
01406         if(nor){
01407             if(mface->flag & ME_SMOOTH)
01408                 interp_v3_v3v3v3(nor, n1, n2, n3, w);
01409             else
01410                 normal_tri_v3(nor,v1,v2,v3);
01411         }
01412     }
01413     
01414     /* calculate tangent vectors */
01415     if(utan && vtan){
01416         if(tface){
01417             uv1= tface->uv[0];
01418             uv2= tface->uv[1];
01419             uv3= tface->uv[2];
01420             uv4= tface->uv[3];
01421         }
01422         else{
01423             uv1= tuv[0]; uv2= tuv[1]; uv3= tuv[2]; uv4= tuv[3];
01424             map_to_sphere( uv1, uv1+1,v1[0], v1[1], v1[2]);
01425             map_to_sphere( uv2, uv2+1,v2[0], v2[1], v2[2]);
01426             map_to_sphere( uv3, uv3+1,v3[0], v3[1], v3[2]);
01427             if(v4)
01428                 map_to_sphere( uv4, uv4+1,v4[0], v4[1], v4[2]);
01429         }
01430 
01431         if(v4){
01432             s1= uv3[0] - uv1[0];
01433             s2= uv4[0] - uv1[0];
01434 
01435             t1= uv3[1] - uv1[1];
01436             t2= uv4[1] - uv1[1];
01437 
01438             sub_v3_v3v3(e1, v3, v1);
01439             sub_v3_v3v3(e2, v4, v1);
01440         }
01441         else{
01442             s1= uv2[0] - uv1[0];
01443             s2= uv3[0] - uv1[0];
01444 
01445             t1= uv2[1] - uv1[1];
01446             t2= uv3[1] - uv1[1];
01447 
01448             sub_v3_v3v3(e1, v2, v1);
01449             sub_v3_v3v3(e2, v3, v1);
01450         }
01451 
01452         vtan[0] = (s1*e2[0] - s2*e1[0]);
01453         vtan[1] = (s1*e2[1] - s2*e1[1]);
01454         vtan[2] = (s1*e2[2] - s2*e1[2]);
01455 
01456         utan[0] = (t1*e2[0] - t2*e1[0]);
01457         utan[1] = (t1*e2[1] - t2*e1[1]);
01458         utan[2] = (t1*e2[2] - t2*e1[2]);
01459     }
01460 
01461     if(orco) {
01462         if(orcodata) {
01463             o1= orcodata[mface->v1];
01464             o2= orcodata[mface->v2];
01465             o3= orcodata[mface->v3];
01466 
01467             if(mface->v4) {
01468                 o4= orcodata[mface->v4];
01469 
01470                 interp_v3_v3v3v3v3(orco, o1, o2, o3, o4, w);
01471 
01472                 if(ornor)
01473                     normal_quad_v3( ornor,o1, o2, o3, o4);
01474             }
01475             else {
01476                 interp_v3_v3v3v3(orco, o1, o2, o3, w);
01477 
01478                 if(ornor)
01479                     normal_tri_v3( ornor,o1, o2, o3);
01480             }
01481         }
01482         else {
01483             copy_v3_v3(orco, vec);
01484             if(ornor && nor)
01485                 copy_v3_v3(ornor, nor);
01486         }
01487     }
01488 }
01489 void psys_interpolate_uvs(const MTFace *tface, int quad, const float w[4], float uvco[2])
01490 {
01491     float v10= tface->uv[0][0];
01492     float v11= tface->uv[0][1];
01493     float v20= tface->uv[1][0];
01494     float v21= tface->uv[1][1];
01495     float v30= tface->uv[2][0];
01496     float v31= tface->uv[2][1];
01497     float v40,v41;
01498 
01499     if(quad) {
01500         v40= tface->uv[3][0];
01501         v41= tface->uv[3][1];
01502 
01503         uvco[0]= w[0]*v10 + w[1]*v20 + w[2]*v30 + w[3]*v40;
01504         uvco[1]= w[0]*v11 + w[1]*v21 + w[2]*v31 + w[3]*v41;
01505     }
01506     else {
01507         uvco[0]= w[0]*v10 + w[1]*v20 + w[2]*v30;
01508         uvco[1]= w[0]*v11 + w[1]*v21 + w[2]*v31;
01509     }
01510 }
01511 
01512 void psys_interpolate_mcol(const MCol *mcol, int quad, const float w[4], MCol *mc)
01513 {
01514     char *cp, *cp1, *cp2, *cp3, *cp4;
01515 
01516     cp= (char *)mc;
01517     cp1= (char *)&mcol[0];
01518     cp2= (char *)&mcol[1];
01519     cp3= (char *)&mcol[2];
01520     
01521     if(quad) {
01522         cp4= (char *)&mcol[3];
01523 
01524         cp[0]= (int)(w[0]*cp1[0] + w[1]*cp2[0] + w[2]*cp3[0] + w[3]*cp4[0]);
01525         cp[1]= (int)(w[0]*cp1[1] + w[1]*cp2[1] + w[2]*cp3[1] + w[3]*cp4[1]);
01526         cp[2]= (int)(w[0]*cp1[2] + w[1]*cp2[2] + w[2]*cp3[2] + w[3]*cp4[2]);
01527         cp[3]= (int)(w[0]*cp1[3] + w[1]*cp2[3] + w[2]*cp3[3] + w[3]*cp4[3]);
01528     }
01529     else {
01530         cp[0]= (int)(w[0]*cp1[0] + w[1]*cp2[0] + w[2]*cp3[0]);
01531         cp[1]= (int)(w[0]*cp1[1] + w[1]*cp2[1] + w[2]*cp3[1]);
01532         cp[2]= (int)(w[0]*cp1[2] + w[1]*cp2[2] + w[2]*cp3[2]);
01533         cp[3]= (int)(w[0]*cp1[3] + w[1]*cp2[3] + w[2]*cp3[3]);
01534     }
01535 }
01536 
01537 static float psys_interpolate_value_from_verts(DerivedMesh *dm, short from, int index, const float fw[4], const float *values)
01538 {
01539     if(values==0 || index==-1)
01540         return 0.0;
01541 
01542     switch(from){
01543         case PART_FROM_VERT:
01544             return values[index];
01545         case PART_FROM_FACE:
01546         case PART_FROM_VOLUME:
01547         {
01548             MFace *mf=dm->getFaceData(dm,index,CD_MFACE);
01549             return interpolate_particle_value(values[mf->v1],values[mf->v2],values[mf->v3],values[mf->v4],fw,mf->v4);
01550         }
01551             
01552     }
01553     return 0.0f;
01554 }
01555 
01556 /* conversion of pa->fw to origspace layer coordinates */
01557 static void psys_w_to_origspace(const float w[4], float uv[2])
01558 {
01559     uv[0]= w[1] + w[2];
01560     uv[1]= w[2] + w[3];
01561 }
01562 
01563 /* conversion of pa->fw to weights in face from origspace */
01564 static void psys_origspace_to_w(OrigSpaceFace *osface, int quad, const float w[4], float neww[4])
01565 {
01566     float v[4][3], co[3];
01567 
01568     v[0][0]= osface->uv[0][0]; v[0][1]= osface->uv[0][1]; v[0][2]= 0.0f;
01569     v[1][0]= osface->uv[1][0]; v[1][1]= osface->uv[1][1]; v[1][2]= 0.0f;
01570     v[2][0]= osface->uv[2][0]; v[2][1]= osface->uv[2][1]; v[2][2]= 0.0f;
01571 
01572     psys_w_to_origspace(w, co);
01573     co[2]= 0.0f;
01574     
01575     if(quad) {
01576         v[3][0]= osface->uv[3][0]; v[3][1]= osface->uv[3][1]; v[3][2]= 0.0f;
01577         interp_weights_poly_v3(neww, v, 4, co);
01578     }
01579     else {
01580         interp_weights_poly_v3(neww, v, 3, co);
01581         neww[3]= 0.0f;
01582     }
01583 }
01584 
01585 /* find the derived mesh face for a particle, set the mf passed. this is slow
01586  * and can be optimized but only for many lookups. returns the face index. */
01587 int psys_particle_dm_face_lookup(Object *ob, DerivedMesh *dm, int index, const float fw[4], struct LinkNode *node)
01588 {
01589     Mesh *me= (Mesh*)ob->data;
01590     MFace *mface;
01591     OrigSpaceFace *osface;
01592     int *origindex;
01593     int quad, findex, totface;
01594     float uv[2], (*faceuv)[2];
01595 
01596     mface = dm->getFaceDataArray(dm, CD_MFACE);
01597     origindex = dm->getFaceDataArray(dm, CD_ORIGINDEX);
01598     osface = dm->getFaceDataArray(dm, CD_ORIGSPACE);
01599 
01600     totface = dm->getNumFaces(dm);
01601     
01602     if(osface==NULL || origindex==NULL) {
01603         /* Assume we dont need osface data */
01604         if (index <totface) {
01605             //printf("\tNO CD_ORIGSPACE, assuming not needed\n");
01606             return index;
01607         } else {
01608             printf("\tNO CD_ORIGSPACE, error out of range\n");
01609             return DMCACHE_NOTFOUND;
01610         }
01611     }
01612     else if(index >= me->totface)
01613         return DMCACHE_NOTFOUND; /* index not in the original mesh */
01614 
01615     psys_w_to_origspace(fw, uv);
01616     
01617     if(node) { /* we have a linked list of faces that we use, faster! */
01618         for(;node; node=node->next) {
01619             findex= GET_INT_FROM_POINTER(node->link);
01620             faceuv= osface[findex].uv;
01621             quad= mface[findex].v4;
01622 
01623             /* check that this intersects - Its possible this misses :/ -
01624              * could also check its not between */
01625             if(quad) {
01626                 if(isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3]))
01627                     return findex;
01628             }
01629             else if(isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2]))
01630                 return findex;
01631         }
01632     }
01633     else { /* if we have no node, try every face */
01634         for(findex=0; findex<totface; findex++) {
01635             if(origindex[findex] == index) {
01636                 faceuv= osface[findex].uv;
01637                 quad= mface[findex].v4;
01638 
01639                 /* check that this intersects - Its possible this misses :/ -
01640                  * could also check its not between */
01641                 if(quad) {
01642                     if(isect_point_quad_v2(uv, faceuv[0], faceuv[1], faceuv[2], faceuv[3]))
01643                         return findex;
01644                 }
01645                 else if(isect_point_tri_v2(uv, faceuv[0], faceuv[1], faceuv[2]))
01646                     return findex;
01647             }
01648         }
01649     }
01650 
01651     return DMCACHE_NOTFOUND;
01652 }
01653 
01654 static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache, const float fw[4], float UNUSED(foffset), int *mapindex, float mapfw[4])
01655 {
01656     if(index < 0)
01657         return 0;
01658 
01659     if (dm->deformedOnly || index_dmcache == DMCACHE_ISCHILD) {
01660         /* for meshes that are either only defined or for child particles, the
01661          * index and fw do not require any mapping, so we can directly use it */
01662         if(from == PART_FROM_VERT) {
01663             if(index >= dm->getNumVerts(dm))
01664                 return 0;
01665 
01666             *mapindex = index;
01667         }
01668         else  { /* FROM_FACE/FROM_VOLUME */
01669             if(index >= dm->getNumFaces(dm))
01670                 return 0;
01671 
01672             *mapindex = index;
01673             copy_v4_v4(mapfw, fw);
01674         }
01675     } else {
01676         /* for other meshes that have been modified, we try to map the particle
01677          * to their new location, which means a different index, and for faces
01678          * also a new face interpolation weights */
01679         if(from == PART_FROM_VERT) {
01680             if (index_dmcache == DMCACHE_NOTFOUND || index_dmcache > dm->getNumVerts(dm))
01681                 return 0;
01682 
01683             *mapindex = index_dmcache;
01684         }
01685         else  { /* FROM_FACE/FROM_VOLUME */
01686             /* find a face on the derived mesh that uses this face */
01687             MFace *mface;
01688             OrigSpaceFace *osface;
01689             int i;
01690 
01691             i = index_dmcache;
01692 
01693             if(i== DMCACHE_NOTFOUND || i >= dm->getNumFaces(dm))
01694                 return 0;
01695 
01696             *mapindex = i;
01697 
01698             /* modify the original weights to become
01699              * weights for the derived mesh face */
01700             osface= dm->getFaceDataArray(dm, CD_ORIGSPACE);
01701             mface= dm->getFaceData(dm, i, CD_MFACE);
01702 
01703             if(osface == NULL)
01704                 mapfw[0]= mapfw[1]= mapfw[2]= mapfw[3]= 0.0f;
01705             else
01706                 psys_origspace_to_w(&osface[i], mface->v4, fw, mapfw);
01707         }
01708     }
01709 
01710     return 1;
01711 }
01712 
01713 /* interprets particle data to get a point on a mesh in object space */
01714 void psys_particle_on_dm(DerivedMesh *dm, int from, int index, int index_dmcache, const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3], float orco[3], float ornor[3])
01715 {
01716     float tmpnor[3], mapfw[4];
01717     float (*orcodata)[3];
01718     int mapindex;
01719 
01720     if(!psys_map_index_on_dm(dm, from, index, index_dmcache, fw, foffset, &mapindex, mapfw)) {
01721         if(vec) { vec[0]=vec[1]=vec[2]=0.0; }
01722         if(nor) { nor[0]=nor[1]=0.0; nor[2]=1.0; }
01723         if(orco) { orco[0]=orco[1]=orco[2]=0.0; }
01724         if(ornor) { ornor[0]=ornor[1]=0.0; ornor[2]=1.0; }
01725         if(utan) { utan[0]=utan[1]=utan[2]=0.0; }
01726         if(vtan) { vtan[0]=vtan[1]=vtan[2]=0.0; }
01727 
01728         return;
01729     }
01730 
01731     orcodata= dm->getVertDataArray(dm, CD_ORCO);
01732 
01733     if(from == PART_FROM_VERT) {
01734         dm->getVertCo(dm,mapindex,vec);
01735 
01736         if(nor) {
01737             dm->getVertNo(dm,mapindex,nor);
01738             normalize_v3(nor);
01739         }
01740 
01741         if(orco)
01742             copy_v3_v3(orco, orcodata[mapindex]);
01743 
01744         if(ornor) {
01745             dm->getVertNo(dm,mapindex,nor);
01746             normalize_v3(nor);
01747         }
01748 
01749         if(utan && vtan) {
01750             utan[0]= utan[1]= utan[2]= 0.0f;
01751             vtan[0]= vtan[1]= vtan[2]= 0.0f;
01752         }
01753     }
01754     else { /* PART_FROM_FACE / PART_FROM_VOLUME */
01755         MFace *mface;
01756         MTFace *mtface;
01757         MVert *mvert;
01758 
01759         mface=dm->getFaceData(dm,mapindex,CD_MFACE);
01760         mvert=dm->getVertDataArray(dm,CD_MVERT);
01761         mtface=CustomData_get_layer(&dm->faceData,CD_MTFACE);
01762 
01763         if(mtface)
01764             mtface += mapindex;
01765 
01766         if(from==PART_FROM_VOLUME) {
01767             psys_interpolate_face(mvert,mface,mtface,orcodata,mapfw,vec,tmpnor,utan,vtan,orco,ornor);
01768             if(nor)
01769                 copy_v3_v3(nor,tmpnor);
01770 
01771             normalize_v3(tmpnor);
01772             mul_v3_fl(tmpnor,-foffset);
01773             add_v3_v3(vec, tmpnor);
01774         }
01775         else
01776             psys_interpolate_face(mvert,mface,mtface,orcodata,mapfw,vec,nor,utan,vtan,orco,ornor);
01777     }
01778 }
01779 
01780 float psys_particle_value_from_verts(DerivedMesh *dm, short from, ParticleData *pa, float *values)
01781 {
01782     float mapfw[4];
01783     int mapindex;
01784 
01785     if(!psys_map_index_on_dm(dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, &mapindex, mapfw))
01786         return 0.0f;
01787     
01788     return psys_interpolate_value_from_verts(dm, from, mapindex, mapfw, values);
01789 }
01790 
01791 ParticleSystemModifierData *psys_get_modifier(Object *ob, ParticleSystem *psys)
01792 {
01793     ModifierData *md;
01794     ParticleSystemModifierData *psmd;
01795 
01796     for(md=ob->modifiers.first; md; md=md->next){
01797         if(md->type==eModifierType_ParticleSystem){
01798             psmd= (ParticleSystemModifierData*) md;
01799             if(psmd->psys==psys){
01800                 return psmd;
01801             }
01802         }
01803     }
01804     return NULL;
01805 }
01806 /************************************************/
01807 /*          Particles on a shape                */
01808 /************************************************/
01809 /* ready for future use */
01810 static void psys_particle_on_shape(int UNUSED(distr), int UNUSED(index), float *UNUSED(fuv), float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor)
01811 {
01812     /* TODO */
01813     float zerovec[3]={0.0f,0.0f,0.0f};
01814     if(vec){
01815         copy_v3_v3(vec,zerovec);
01816     }
01817     if(nor){
01818         copy_v3_v3(nor,zerovec);
01819     }
01820     if(utan){
01821         copy_v3_v3(utan,zerovec);
01822     }
01823     if(vtan){
01824         copy_v3_v3(vtan,zerovec);
01825     }
01826     if(orco){
01827         copy_v3_v3(orco,zerovec);
01828     }
01829     if(ornor){
01830         copy_v3_v3(ornor,zerovec);
01831     }
01832 }
01833 /************************************************/
01834 /*          Particles on emitter                */
01835 /************************************************/
01836 void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int index, int index_dmcache, float *fuv, float foffset, float *vec, float *nor, float *utan, float *vtan, float *orco, float *ornor)
01837 {
01838     if(psmd){
01839         if(psmd->psys->part->distr==PART_DISTR_GRID && psmd->psys->part->from != PART_FROM_VERT){
01840             if(vec)
01841                 copy_v3_v3(vec,fuv);
01842 
01843             if(orco)
01844                 copy_v3_v3(orco, fuv);
01845             return;
01846         }
01847         /* we cant use the num_dmcache */
01848         psys_particle_on_dm(psmd->dm,from,index,index_dmcache,fuv,foffset,vec,nor,utan,vtan,orco,ornor);
01849     }
01850     else
01851         psys_particle_on_shape(from,index,fuv,vec,nor,utan,vtan,orco,ornor);
01852 
01853 }
01854 /************************************************/
01855 /*          Path Cache                          */
01856 /************************************************/
01857 
01858 static void do_kink(ParticleKey *state, ParticleKey *par, float *par_rot, float time, float freq, float shape, float amplitude, float flat, short type, short axis, float obmat[][4], int smooth_start)
01859 {
01860     float kink[3]={1.f,0.f,0.f}, par_vec[3], q1[4]={1.f,0.f,0.f,0.f};
01861     float t, dt=1.f, result[3];
01862 
01863     if(par == NULL || type == PART_KINK_NO)
01864         return;
01865 
01866     CLAMP(time, 0.f, 1.f);
01867 
01868     if(shape!=0.0f && type!=PART_KINK_BRAID) {
01869         if(shape<0.0f)
01870             time= (float)pow(time, 1.f+shape);
01871         else
01872             time= (float)pow(time, 1.f/(1.f-shape));
01873     }
01874 
01875     t = time * freq *(float)M_PI;
01876     
01877     if(smooth_start) {
01878         dt = fabs(t);
01879         /* smooth the beginning of kink */
01880         CLAMP(dt, 0.f, (float)M_PI);
01881         dt = sin(dt/2.f);
01882     }
01883 
01884     if(type != PART_KINK_RADIAL) {
01885         float temp[3];
01886 
01887         kink[axis]=1.f;
01888 
01889         if(obmat)
01890             mul_mat3_m4_v3(obmat, kink);
01891         
01892         if(par_rot)
01893             mul_qt_v3(par_rot, kink);
01894 
01895         /* make sure kink is normal to strand */
01896         project_v3_v3v3(temp, kink, par->vel);
01897         sub_v3_v3(kink, temp);
01898         normalize_v3(kink);
01899     }
01900 
01901     copy_v3_v3(result, state->co);
01902     sub_v3_v3v3(par_vec, par->co, state->co);
01903 
01904     switch(type) {
01905     case PART_KINK_CURL:
01906     {
01907         negate_v3(par_vec);
01908 
01909         if(flat > 0.f) {
01910             float proj[3];
01911             project_v3_v3v3(proj, par_vec, par->vel);
01912             madd_v3_v3fl(par_vec, proj, -flat);
01913 
01914             project_v3_v3v3(proj, par_vec, kink);
01915             madd_v3_v3fl(par_vec, proj, -flat);
01916         }
01917 
01918         axis_angle_to_quat(q1, kink, (float)M_PI/2.f);
01919 
01920         mul_qt_v3(q1, par_vec);
01921 
01922         madd_v3_v3fl(par_vec, kink, amplitude);
01923 
01924         /* rotate kink vector around strand tangent */
01925         if(t!=0.f) {
01926             axis_angle_to_quat(q1, par->vel, t);
01927             mul_qt_v3(q1, par_vec);
01928         }
01929 
01930         add_v3_v3v3(result, par->co, par_vec);
01931         break;
01932     }
01933     case PART_KINK_RADIAL:
01934     {
01935         if(flat > 0.f) {
01936             float proj[3];
01937             /* flatten along strand */
01938             project_v3_v3v3(proj, par_vec, par->vel);
01939             madd_v3_v3fl(result, proj, flat);
01940         }
01941 
01942         madd_v3_v3fl(result, par_vec, -amplitude*(float)sin(t));
01943         break;
01944     }
01945     case PART_KINK_WAVE:
01946     {
01947         madd_v3_v3fl(result, kink, amplitude*(float)sin(t));
01948 
01949         if(flat > 0.f) {
01950             float proj[3];
01951             /* flatten along wave */
01952             project_v3_v3v3(proj, par_vec, kink);
01953             madd_v3_v3fl(result, proj, flat);
01954 
01955             /* flatten along strand */
01956             project_v3_v3v3(proj, par_vec, par->vel);
01957             madd_v3_v3fl(result, proj, flat);
01958         }
01959         break;
01960     }
01961     case PART_KINK_BRAID:
01962     {
01963         float y_vec[3]={0.f,1.f,0.f};
01964         float z_vec[3]={0.f,0.f,1.f};
01965         float vec_one[3], state_co[3];
01966         float inp_y, inp_z, length;
01967 
01968         if(par_rot) {
01969             mul_qt_v3(par_rot, y_vec);
01970             mul_qt_v3(par_rot, z_vec);
01971         }
01972         
01973         negate_v3(par_vec);
01974         normalize_v3_v3(vec_one, par_vec);
01975 
01976         inp_y=dot_v3v3(y_vec, vec_one);
01977         inp_z=dot_v3v3(z_vec, vec_one);
01978 
01979         if(inp_y > 0.5f){
01980             copy_v3_v3(state_co, y_vec);
01981 
01982             mul_v3_fl(y_vec, amplitude*(float)cos(t));
01983             mul_v3_fl(z_vec, amplitude/2.f*(float)sin(2.f*t));
01984         }
01985         else if(inp_z > 0.0f){
01986             mul_v3_v3fl(state_co, z_vec, (float)sin((float)M_PI/3.f));
01987             madd_v3_v3fl(state_co, y_vec, -0.5f);
01988 
01989             mul_v3_fl(y_vec, -amplitude * (float)cos(t + (float)M_PI/3.f));
01990             mul_v3_fl(z_vec, amplitude/2.f * (float)cos(2.f*t + (float)M_PI/6.f));
01991         }
01992         else{
01993             mul_v3_v3fl(state_co, z_vec, -(float)sin((float)M_PI/3.f));
01994             madd_v3_v3fl(state_co, y_vec, -0.5f);
01995 
01996             mul_v3_fl(y_vec, amplitude * (float)-sin(t + (float)M_PI/6.f));
01997             mul_v3_fl(z_vec, amplitude/2.f * (float)-sin(2.f*t + (float)M_PI/3.f));
01998         }
01999 
02000         mul_v3_fl(state_co, amplitude);
02001         add_v3_v3(state_co, par->co);
02002         sub_v3_v3v3(par_vec, state->co, state_co);
02003 
02004         length = normalize_v3(par_vec);
02005         mul_v3_fl(par_vec, MIN2(length, amplitude/2.f));
02006 
02007         add_v3_v3v3(state_co, par->co, y_vec);
02008         add_v3_v3(state_co, z_vec);
02009         add_v3_v3(state_co, par_vec);
02010 
02011         shape = 2.f*(float)M_PI * (1.f+shape);
02012 
02013         if(t<shape){
02014             shape = t/shape;
02015             shape = (float)sqrt((double)shape);
02016             interp_v3_v3v3(result, result, state_co, shape);
02017         }
02018         else{
02019             copy_v3_v3(result, state_co);
02020         }
02021         break;
02022     }
02023     }
02024 
02025     /* blend the start of the kink */
02026     if(dt < 1.f)
02027         interp_v3_v3v3(state->co, state->co, result, dt);
02028     else
02029         copy_v3_v3(state->co, result);
02030 }
02031 
02032 static float do_clump(ParticleKey *state, ParticleKey *par, float time, float clumpfac, float clumppow, float pa_clump)
02033 {
02034     float clump = 0.f;
02035 
02036     if(par && clumpfac!=0.0f){
02037         float cpow;
02038 
02039         if(clumppow < 0.0f)
02040             cpow=1.0f+clumppow;
02041         else
02042             cpow=1.0f+9.0f*clumppow;
02043 
02044         if(clumpfac < 0.0f) /* clump roots instead of tips */
02045             clump = -clumpfac*pa_clump*(float)pow(1.0-(double)time,(double)cpow);
02046         else
02047             clump = clumpfac*pa_clump*(float)pow((double)time,(double)cpow);
02048 
02049         interp_v3_v3v3(state->co,state->co,par->co,clump);
02050     }
02051 
02052     return clump;
02053 }
02054 void precalc_guides(ParticleSimulationData *sim, ListBase *effectors)
02055 {
02056     EffectedPoint point;
02057     ParticleKey state;
02058     EffectorData efd;
02059     EffectorCache *eff;
02060     ParticleSystem *psys = sim->psys;
02061     EffectorWeights *weights = sim->psys->part->effector_weights;
02062     GuideEffectorData *data;
02063     PARTICLE_P;
02064 
02065     if(!effectors)
02066         return;
02067 
02068     LOOP_PARTICLES {
02069         psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,state.co,0,0,0,0,0);
02070         
02071         mul_m4_v3(sim->ob->obmat, state.co);
02072         mul_mat3_m4_v3(sim->ob->obmat, state.vel);
02073         
02074         pd_point_from_particle(sim, pa, &state, &point);
02075 
02076         for(eff = effectors->first; eff; eff=eff->next) {
02077             if(eff->pd->forcefield != PFIELD_GUIDE)
02078                 continue;
02079 
02080             if(!eff->guide_data)
02081                 eff->guide_data = MEM_callocN(sizeof(GuideEffectorData)*psys->totpart, "GuideEffectorData");
02082 
02083             data = eff->guide_data + p;
02084 
02085             sub_v3_v3v3(efd.vec_to_point, state.co, eff->guide_loc);
02086             copy_v3_v3(efd.nor, eff->guide_dir);
02087             efd.distance = len_v3(efd.vec_to_point);
02088 
02089             copy_v3_v3(data->vec_to_point, efd.vec_to_point);
02090             data->strength = effector_falloff(eff, &efd, &point, weights);
02091         }
02092     }
02093 }
02094 int do_guides(ListBase *effectors, ParticleKey *state, int index, float time)
02095 {
02096     EffectorCache *eff;
02097     PartDeflect *pd;
02098     Curve *cu;
02099     ParticleKey key, par;
02100     GuideEffectorData *data;
02101 
02102     float effect[3] = {0.0f, 0.0f, 0.0f}, veffect[3] = {0.0f, 0.0f, 0.0f};
02103     float guidevec[4], guidedir[3], rot2[4], temp[3];
02104     float guidetime, radius, weight, angle, totstrength = 0.0f;
02105     float vec_to_point[3];
02106 
02107     if(effectors) for(eff = effectors->first; eff; eff=eff->next) {
02108         pd = eff->pd;
02109 
02110         if(pd->forcefield != PFIELD_GUIDE)
02111             continue;
02112 
02113         data = eff->guide_data + index;
02114 
02115         if(data->strength <= 0.0f)
02116             continue;
02117 
02118         guidetime = time / (1.0f - pd->free_end);
02119 
02120         if(guidetime>1.0f)
02121             continue;
02122 
02123         cu = (Curve*)eff->ob->data;
02124 
02125         if(pd->flag & PFIELD_GUIDE_PATH_ADD) {
02126             if(where_on_path(eff->ob, data->strength * guidetime, guidevec, guidedir, NULL, &radius, &weight)==0)
02127                 return 0;
02128         }
02129         else {
02130             if(where_on_path(eff->ob, guidetime, guidevec, guidedir, NULL, &radius, &weight)==0)
02131                 return 0;
02132         }
02133 
02134         mul_m4_v3(eff->ob->obmat, guidevec);
02135         mul_mat3_m4_v3(eff->ob->obmat, guidedir);
02136 
02137         normalize_v3(guidedir);
02138 
02139         copy_v3_v3(vec_to_point, data->vec_to_point);
02140 
02141         if(guidetime != 0.0f) {
02142             /* curve direction */
02143             cross_v3_v3v3(temp, eff->guide_dir, guidedir);
02144             angle = dot_v3v3(eff->guide_dir, guidedir)/(len_v3(eff->guide_dir));
02145             angle = saacos(angle);
02146             axis_angle_to_quat( rot2,temp, angle);
02147             mul_qt_v3(rot2, vec_to_point);
02148 
02149             /* curve tilt */
02150             axis_angle_to_quat( rot2,guidedir, guidevec[3] - eff->guide_loc[3]);
02151             mul_qt_v3(rot2, vec_to_point);
02152         }
02153 
02154         /* curve taper */
02155         if(cu->taperobj)
02156             mul_v3_fl(vec_to_point, calc_taper(eff->scene, cu->taperobj, (int)(data->strength*guidetime*100.0f), 100));
02157 
02158         else{ /* curve size*/
02159             if(cu->flag & CU_PATH_RADIUS) {
02160                 mul_v3_fl(vec_to_point, radius);
02161             }
02162         }
02163         par.co[0] = par.co[1] = par.co[2] = 0.0f;
02164         copy_v3_v3(key.co, vec_to_point);
02165         do_kink(&key, &par, 0, guidetime, pd->kink_freq, pd->kink_shape, pd->kink_amp, 0.f, pd->kink, pd->kink_axis, 0, 0);
02166         do_clump(&key, &par, guidetime, pd->clump_fac, pd->clump_pow, 1.0f);
02167         copy_v3_v3(vec_to_point, key.co);
02168 
02169         add_v3_v3(vec_to_point, guidevec);
02170 
02171         //sub_v3_v3v3(pa_loc,pa_loc,pa_zero);
02172         madd_v3_v3fl(effect, vec_to_point, data->strength);
02173         madd_v3_v3fl(veffect, guidedir, data->strength);
02174         totstrength += data->strength;
02175 
02176         if(pd->flag & PFIELD_GUIDE_PATH_WEIGHT)
02177             totstrength *= weight;
02178     }
02179 
02180     if(totstrength != 0.0f){
02181         if(totstrength > 1.0f)
02182             mul_v3_fl(effect, 1.0f / totstrength);
02183         CLAMP(totstrength, 0.0f, 1.0f);
02184         //add_v3_v3(effect,pa_zero);
02185         interp_v3_v3v3(state->co, state->co, effect, totstrength);
02186 
02187         normalize_v3(veffect);
02188         mul_v3_fl(veffect, len_v3(state->vel));
02189         copy_v3_v3(state->vel, veffect);
02190         return 1;
02191     }
02192     return 0;
02193 }
02194 static void do_rough(float *loc, float mat[4][4], float t, float fac, float size, float thres, ParticleKey *state)
02195 {
02196     float rough[3];
02197     float rco[3];
02198 
02199     if(thres != 0.0f)
02200         if((float)fabs((float)(-1.5f+loc[0]+loc[1]+loc[2]))<1.5f*thres) return;
02201 
02202     copy_v3_v3(rco,loc);
02203     mul_v3_fl(rco,t);
02204     rough[0]=-1.0f+2.0f*BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2,0,2);
02205     rough[1]=-1.0f+2.0f*BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2,0,2);
02206     rough[2]=-1.0f+2.0f*BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2,0,2);
02207 
02208     madd_v3_v3fl(state->co, mat[0], fac * rough[0]);
02209     madd_v3_v3fl(state->co, mat[1], fac * rough[1]);
02210     madd_v3_v3fl(state->co, mat[2], fac * rough[2]);
02211 }
02212 static void do_rough_end(float *loc, float mat[4][4], float t, float fac, float shape, ParticleKey *state)
02213 {
02214     float rough[2];
02215     float roughfac;
02216 
02217     roughfac=fac*(float)pow((double)t,shape);
02218     copy_v2_v2(rough,loc);
02219     rough[0]=-1.0f+2.0f*rough[0];
02220     rough[1]=-1.0f+2.0f*rough[1];
02221     mul_v2_fl(rough,roughfac);
02222 
02223     madd_v3_v3fl(state->co, mat[0], rough[0]);
02224     madd_v3_v3fl(state->co, mat[1], rough[1]);
02225 }
02226 static void do_path_effectors(ParticleSimulationData *sim, int i, ParticleCacheKey *ca, int k, int steps, float *UNUSED(rootco), float effector, float UNUSED(dfra), float UNUSED(cfra), float *length, float *vec)
02227 {
02228     float force[3] = {0.0f,0.0f,0.0f};
02229     ParticleKey eff_key;
02230     EffectedPoint epoint;
02231 
02232     /* Don't apply effectors for dynamic hair, otherwise the effectors don't get applied twice. */
02233     if(sim->psys->flag & PSYS_HAIR_DYNAMICS)
02234         return;
02235 
02236     copy_v3_v3(eff_key.co,(ca-1)->co);
02237     copy_v3_v3(eff_key.vel,(ca-1)->vel);
02238     copy_qt_qt(eff_key.rot,(ca-1)->rot);
02239 
02240     pd_point_from_particle(sim, sim->psys->particles+i, &eff_key, &epoint);
02241     pdDoEffectors(sim->psys->effectors, sim->colliders, sim->psys->part->effector_weights, &epoint, force, NULL);
02242 
02243     mul_v3_fl(force, effector*powf((float)k / (float)steps, 100.0f * sim->psys->part->eff_hair) / (float)steps);
02244 
02245     add_v3_v3(force, vec);
02246 
02247     normalize_v3(force);
02248 
02249     if(k < steps)
02250         sub_v3_v3v3(vec, (ca+1)->co, ca->co);
02251 
02252     madd_v3_v3v3fl(ca->co, (ca-1)->co, force, *length);
02253 
02254     if(k < steps)
02255         *length = len_v3(vec);
02256 }
02257 static int check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *state, float max_length, float *cur_length, float length, float *dvec)
02258 {
02259     if(*cur_length + length > max_length){
02260         mul_v3_fl(dvec, (max_length - *cur_length) / length);
02261         add_v3_v3v3(state->co, (state - 1)->co, dvec);
02262         keys->steps = k;
02263         /* something over the maximum step value */
02264         return k=100000;
02265     }
02266     else {
02267         *cur_length+=length;
02268         return k;
02269     }
02270 }
02271 static void offset_child(ChildParticle *cpa, ParticleKey *par, float *par_rot, ParticleKey *child, float flat, float radius)
02272 {
02273     copy_v3_v3(child->co, cpa->fuv);
02274     mul_v3_fl(child->co, radius);
02275 
02276     child->co[0]*=flat;
02277 
02278     copy_v3_v3(child->vel, par->vel);
02279 
02280     if(par_rot) {
02281         mul_qt_v3(par_rot, child->co);
02282         copy_qt_qt(child->rot, par_rot);
02283     }
02284     else
02285         unit_qt(child->rot);
02286 
02287     add_v3_v3(child->co, par->co);
02288 }
02289 float *psys_cache_vgroup(DerivedMesh *dm, ParticleSystem *psys, int vgroup)
02290 {
02291     float *vg=0;
02292 
02293     if(vgroup < 0) {
02294         /* hair dynamics pinning vgroup */
02295 
02296     }
02297     else if(psys->vgroup[vgroup]){
02298         MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT);
02299         if(dvert){
02300             int totvert=dm->getNumVerts(dm), i;
02301             vg=MEM_callocN(sizeof(float)*totvert, "vg_cache");
02302             if(psys->vg_neg&(1<<vgroup)){
02303                 for(i=0; i<totvert; i++)
02304                     vg[i]= 1.0f - defvert_find_weight(&dvert[i], psys->vgroup[vgroup] - 1);
02305             }
02306             else{
02307                 for(i=0; i<totvert; i++)
02308                     vg[i]=  defvert_find_weight(&dvert[i], psys->vgroup[vgroup] - 1);
02309             }
02310         }
02311     }
02312     return vg;
02313 }
02314 void psys_find_parents(ParticleSimulationData *sim)
02315 {
02316     ParticleSettings *part=sim->psys->part;
02317     KDTree *tree;
02318     ChildParticle *cpa;
02319     int p, totparent,totchild=sim->psys->totchild;
02320     float co[3], orco[3];
02321     int from=PART_FROM_FACE;
02322     totparent=(int)(totchild*part->parents*0.3f);
02323 
02324     if(G.rendering && part->child_nbr && part->ren_child_nbr)
02325         totparent*=(float)part->child_nbr/(float)part->ren_child_nbr;
02326 
02327     tree=BLI_kdtree_new(totparent);
02328 
02329     for(p=0,cpa=sim->psys->child; p<totparent; p++,cpa++){
02330         psys_particle_on_emitter(sim->psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0);
02331         BLI_kdtree_insert(tree, p, orco, NULL);
02332     }
02333 
02334     BLI_kdtree_balance(tree);
02335 
02336     for(; p<totchild; p++,cpa++){
02337         psys_particle_on_emitter(sim->psmd,from,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co,0,0,0,orco,0);
02338         cpa->parent=BLI_kdtree_find_nearest(tree, orco, NULL, NULL);
02339     }
02340 
02341     BLI_kdtree_free(tree);
02342 }
02343 
02344 static void get_strand_normal(Material *ma, float *surfnor, float surfdist, float *nor)
02345 {
02346     float cross[3], nstrand[3], vnor[3], blend;
02347 
02348     if(!((ma->mode & MA_STR_SURFDIFF) || (ma->strand_surfnor > 0.0f)))
02349         return;
02350 
02351     if(ma->mode & MA_STR_SURFDIFF) {
02352         cross_v3_v3v3(cross, surfnor, nor);
02353         cross_v3_v3v3(nstrand, nor, cross);
02354 
02355         blend= INPR(nstrand, surfnor);
02356         CLAMP(blend, 0.0f, 1.0f);
02357 
02358         interp_v3_v3v3(vnor, nstrand, surfnor, blend);
02359         normalize_v3(vnor);
02360     }
02361     else {
02362         copy_v3_v3(vnor, nor);
02363     }
02364     
02365     if(ma->strand_surfnor > 0.0f) {
02366         if(ma->strand_surfnor > surfdist) {
02367             blend= (ma->strand_surfnor - surfdist)/ma->strand_surfnor;
02368             interp_v3_v3v3(vnor, vnor, surfnor, blend);
02369             normalize_v3(vnor);
02370         }
02371     }
02372 
02373     copy_v3_v3(nor, vnor);
02374 }
02375 
02376 static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float cfra, int editupdate)
02377 {
02378     ParticleThreadContext *ctx= threads[0].ctx;
02379 /*  Object *ob= ctx->sim.ob; */
02380     ParticleSystem *psys= ctx->sim.psys;
02381     ParticleSettings *part = psys->part;
02382 /*  ParticleEditSettings *pset = &scene->toolsettings->particle; */
02383     int totparent=0, between=0;
02384     int steps = (int)pow(2.0, (double)part->draw_step);
02385     int totchild = psys->totchild;
02386     int i, seed, totthread= threads[0].tot;
02387 
02388     /*---start figuring out what is actually wanted---*/
02389     if(psys_in_edit_mode(scene, psys)) {
02390         ParticleEditSettings *pset = &scene->toolsettings->particle;
02391 
02392         if(psys->renderdata==0 && (psys->edit==NULL || pset->flag & PE_DRAW_PART)==0)
02393             totchild=0;
02394 
02395         steps = (int)pow(2.0, (double)pset->draw_step);
02396     }
02397 
02398     if(totchild && part->childtype==PART_CHILD_FACES){
02399         totparent=(int)(totchild*part->parents*0.3f);
02400         
02401         if(G.rendering && part->child_nbr && part->ren_child_nbr)
02402             totparent*=(float)part->child_nbr/(float)part->ren_child_nbr;
02403 
02404         /* part->parents could still be 0 so we can't test with totparent */
02405         between=1;
02406     }
02407 
02408     if(psys->renderdata)
02409         steps=(int)pow(2.0,(double)part->ren_step);
02410     else{
02411         totchild=(int)((float)totchild*(float)part->disp/100.0f);
02412         totparent=MIN2(totparent,totchild);
02413     }
02414 
02415     if(totchild==0) return 0;
02416 
02417     /* init random number generator */
02418     seed= 31415926 + ctx->sim.psys->seed;
02419     
02420     if(ctx->editupdate || totchild < 10000)
02421         totthread= 1;
02422     
02423     for(i=0; i<totthread; i++) {
02424         threads[i].rng_path= rng_new(seed);
02425         threads[i].tot= totthread;
02426     }
02427 
02428     /* fill context values */
02429     ctx->between= between;
02430     ctx->steps= steps;
02431     ctx->totchild= totchild;
02432     ctx->totparent= totparent;
02433     ctx->parent_pass= 0;
02434     ctx->cfra= cfra;
02435     ctx->editupdate= editupdate;
02436 
02437     psys->lattice = psys_get_lattice(&ctx->sim);
02438 
02439     /* cache all relevant vertex groups if they exist */
02440     ctx->vg_length = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_LENGTH);
02441     ctx->vg_clump = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_CLUMP);
02442     ctx->vg_kink = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_KINK);
02443     ctx->vg_rough1 = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGH1);
02444     ctx->vg_rough2 = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGH2);
02445     ctx->vg_roughe = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_ROUGHE);
02446     if(psys->part->flag & PART_CHILD_EFFECT)
02447         ctx->vg_effector = psys_cache_vgroup(ctx->dm,psys,PSYS_VG_EFFECTOR);
02448 
02449     /* set correct ipo timing */
02450 #if 0 // XXX old animation system
02451     if(part->flag&PART_ABS_TIME && part->ipo){
02452         calc_ipo(part->ipo, cfra);
02453         execute_ipo((ID *)part, part->ipo);
02454     }
02455 #endif // XXX old animation system
02456 
02457     return 1;
02458 }
02459 
02460 /* note: this function must be thread safe, except for branching! */
02461 static void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa, ParticleCacheKey *child_keys, int i)
02462 {
02463     ParticleThreadContext *ctx= thread->ctx;
02464     Object *ob= ctx->sim.ob;
02465     ParticleSystem *psys = ctx->sim.psys;
02466     ParticleSettings *part = psys->part;
02467     ParticleCacheKey **cache= psys->childcache;
02468     ParticleCacheKey **pcache= psys_in_edit_mode(ctx->sim.scene, psys) ? psys->edit->pathcache : psys->pathcache;
02469     ParticleCacheKey *child, *par = NULL, *key[4];
02470     ParticleTexture ptex;
02471     float *cpa_fuv=0, *par_rot=0, rot[4];
02472     float orco[3], ornor[3], hairmat[4][4], t, dvec[3], off1[4][3], off2[4][3];
02473     float length, max_length = 1.0f, cur_length = 0.0f;
02474     float eff_length, eff_vec[3], weight[4];
02475     int k, cpa_num;
02476     short cpa_from;
02477 
02478     if(!pcache)
02479         return;
02480 
02481     if(ctx->between){
02482         ParticleData *pa = psys->particles + cpa->pa[0];
02483         int w, needupdate;
02484         float foffset, wsum=0.f;
02485         float co[3];
02486         float p_min = part->parting_min;
02487         float p_max = part->parting_max;
02488         /* Virtual parents don't work nicely with parting. */
02489         float p_fac = part->parents > 0.f ? 0.f : part->parting_fac;
02490 
02491         if(ctx->editupdate) {
02492             needupdate= 0;
02493             w= 0;
02494             while(w<4 && cpa->pa[w]>=0) {
02495                 if(psys->edit->points[cpa->pa[w]].flag & PEP_EDIT_RECALC) {
02496                     needupdate= 1;
02497                     break;
02498                 }
02499                 w++;
02500             }
02501 
02502             if(!needupdate)
02503                 return;
02504             else
02505                 memset(child_keys, 0, sizeof(*child_keys)*(ctx->steps+1));
02506         }
02507 
02508         /* get parent paths */
02509         for(w=0; w<4; w++) {
02510             if(cpa->pa[w] >= 0) {
02511                 key[w] = pcache[cpa->pa[w]];
02512                 weight[w] = cpa->w[w];
02513             }
02514             else {
02515                 key[w] = pcache[0];
02516                 weight[w] = 0.f;
02517             }
02518         }
02519 
02520         /* modify weights to create parting */
02521         if(p_fac > 0.f) {
02522             for(w=0; w<4; w++) {
02523                 if(w && weight[w] > 0.f) {
02524                     float d;
02525                     if(part->flag & PART_CHILD_LONG_HAIR) {
02526                         /* For long hair use tip distance/root distance as parting factor instead of root to tip angle. */
02527                         float d1 = len_v3v3(key[0]->co, key[w]->co);
02528                         float d2 = len_v3v3((key[0]+key[0]->steps-1)->co, (key[w]+key[w]->steps-1)->co);
02529 
02530                         d = d1 > 0.f ? d2/d1 - 1.f : 10000.f;
02531                     }
02532                     else {
02533                         float v1[3], v2[3];
02534                         sub_v3_v3v3(v1, (key[0]+key[0]->steps-1)->co, key[0]->co);
02535                         sub_v3_v3v3(v2, (key[w]+key[w]->steps-1)->co, key[w]->co);
02536                         normalize_v3(v1);
02537                         normalize_v3(v2);
02538 
02539                         d = RAD2DEGF(saacos(dot_v3v3(v1, v2)));
02540                     }
02541 
02542                     if(p_max > p_min)
02543                         d = (d - p_min)/(p_max - p_min);
02544                     else
02545                         d = (d - p_min) <= 0.f ? 0.f : 1.f;
02546 
02547                     CLAMP(d, 0.f, 1.f);
02548 
02549                     if(d > 0.f)
02550                         weight[w] *= (1.f - d);
02551                 }
02552                 wsum += weight[w];
02553             }
02554             for(w=0; w<4; w++)
02555                 weight[w] /= wsum;
02556 
02557             interp_v4_v4v4(weight, cpa->w, weight, p_fac);
02558         }
02559 
02560         /* get the original coordinates (orco) for texture usage */
02561         cpa_num = cpa->num;
02562         
02563         foffset = cpa->foffset;
02564         cpa_fuv = cpa->fuv;
02565         cpa_from = PART_FROM_FACE;
02566 
02567         psys_particle_on_emitter(ctx->sim.psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,ornor,0,0,orco,0);
02568 
02569         mul_m4_v3(ob->obmat, co);
02570 
02571         for(w=0; w<4; w++)
02572             sub_v3_v3v3(off1[w], co, key[w]->co);
02573 
02574         psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat);
02575     }
02576     else{
02577         ParticleData *pa = psys->particles + cpa->parent;
02578         float co[3];
02579         if(ctx->editupdate) {
02580             if(!(psys->edit->points[cpa->parent].flag & PEP_EDIT_RECALC))
02581                 return;
02582 
02583             memset(child_keys, 0, sizeof(*child_keys)*(ctx->steps+1));
02584         }
02585 
02586         /* get the parent path */
02587         key[0] = pcache[cpa->parent];
02588 
02589         /* get the original coordinates (orco) for texture usage */
02590         cpa_from = part->from;
02591         cpa_num = pa->num;
02592         cpa_fuv = pa->fuv;
02593 
02594         psys_particle_on_emitter(ctx->sim.psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,ornor,0,0,orco,0);
02595 
02596         psys_mat_hair_to_global(ob, ctx->sim.psmd->dm, psys->part->from, pa, hairmat);
02597     }
02598 
02599     child_keys->steps = ctx->steps;
02600 
02601     /* get different child parameters from textures & vgroups */
02602     get_child_modifier_parameters(part, ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
02603 
02604     if(ptex.exist < PSYS_FRAND(i + 24)) {
02605         child_keys->steps = -1;
02606         return;
02607     }
02608 
02609     /* create the child path */
02610     for(k=0,child=child_keys; k<=ctx->steps; k++,child++){
02611         if(ctx->between){
02612             int w=0;
02613 
02614             zero_v3(child->co);
02615             zero_v3(child->vel);
02616             unit_qt(child->rot);
02617 
02618             for(w=0; w<4; w++) {
02619                 copy_v3_v3(off2[w], off1[w]);
02620 
02621                 if(part->flag & PART_CHILD_LONG_HAIR) {
02622                     /* Use parent rotation (in addition to emission location) to determine child offset. */
02623                     if(k)
02624                         mul_qt_v3((key[w]+k)->rot, off2[w]);
02625 
02626                     /* Fade the effect of rotation for even lengths in the end */
02627                     project_v3_v3v3(dvec, off2[w], (key[w]+k)->vel);
02628                     madd_v3_v3fl(off2[w], dvec, -(float)k/(float)ctx->steps);
02629                 }
02630 
02631                 add_v3_v3(off2[w], (key[w]+k)->co);
02632             }
02633 
02634             /* child position is the weighted sum of parent positions */
02635             interp_v3_v3v3v3v3(child->co, off2[0], off2[1], off2[2], off2[3], weight);
02636             interp_v3_v3v3v3v3(child->vel, (key[0]+k)->vel, (key[1]+k)->vel, (key[2]+k)->vel, (key[3]+k)->vel, weight);
02637 
02638             copy_qt_qt(child->rot, (key[0]+k)->rot);
02639         }
02640         else{
02641             if(k) {
02642                 mul_qt_qtqt(rot, (key[0]+k)->rot, key[0]->rot);
02643                 par_rot = rot;
02644             }
02645             else {
02646                 par_rot = key[0]->rot;
02647             }
02648             /* offset the child from the parent position */
02649             offset_child(cpa, (ParticleKey*)(key[0]+k), par_rot, (ParticleKey*)child, part->childflat, part->childrad);
02650         }
02651     }
02652 
02653     /* apply effectors */
02654     if(part->flag & PART_CHILD_EFFECT) {
02655         for(k=0,child=child_keys; k<=ctx->steps; k++,child++) {
02656             if(k) {
02657                 do_path_effectors(&ctx->sim, cpa->pa[0], child, k, ctx->steps, child_keys->co, ptex.effector, 0.0f, ctx->cfra, &eff_length, eff_vec);
02658             }
02659             else {
02660                 sub_v3_v3v3(eff_vec, (child+1)->co, child->co);
02661                 eff_length = len_v3(eff_vec);
02662             }
02663         }
02664     }
02665 
02666     for(k=0,child=child_keys; k<=ctx->steps; k++,child++){
02667         t = (float)k/(float)ctx->steps;
02668 
02669         if(ctx->totparent)
02670             /* this is now threadsafe, virtual parents are calculated before rest of children */
02671             par = (i >= ctx->totparent) ? cache[cpa->parent] : NULL;
02672         else if(cpa->parent >= 0)
02673             par = pcache[cpa->parent];
02674 
02675         if(par) {
02676             if(k) {
02677                 mul_qt_qtqt(rot, (par+k)->rot, par->rot);
02678                 par_rot = rot;
02679             }
02680             else {
02681                 par_rot = par->rot;
02682             }
02683             par += k;
02684         }
02685 
02686         /* apply different deformations to the child path */
02687         do_child_modifiers(&ctx->sim, &ptex, (ParticleKey *)par, par_rot, cpa, orco, hairmat, (ParticleKey *)child, t);
02688 
02689         /* we have to correct velocity because of kink & clump */
02690         if(k>1){
02691             sub_v3_v3v3((child-1)->vel, child->co, (child-2)->co);
02692             mul_v3_fl((child-1)->vel, 0.5);
02693 
02694             if(ctx->ma && (part->draw_col == PART_DRAW_COL_MAT))
02695                 get_strand_normal(ctx->ma, ornor, cur_length, (child-1)->vel);
02696         }
02697 
02698         if(k == ctx->steps)
02699             sub_v3_v3v3(child->vel, child->co, (child-1)->co);
02700 
02701         /* check if path needs to be cut before actual end of data points */
02702         if(k){
02703             sub_v3_v3v3(dvec, child->co, (child-1)->co);
02704             length = 1.0f/(float)ctx->steps;
02705             k = check_path_length(k, child_keys, child, max_length, &cur_length, length, dvec);
02706         }
02707         else{
02708             /* initialize length calculation */
02709             max_length = ptex.length;
02710             cur_length = 0.0f;
02711         }
02712 
02713         if(ctx->ma && (part->draw_col == PART_DRAW_COL_MAT)) {
02714             copy_v3_v3(child->col, &ctx->ma->r);
02715             get_strand_normal(ctx->ma, ornor, cur_length, child->vel);
02716         }
02717     }
02718 
02719     /* Hide virtual parents */
02720     if(i < ctx->totparent)
02721         child_keys->steps = -1;
02722 }
02723 
02724 static void *exec_child_path_cache(void *data)
02725 {
02726     ParticleThread *thread= (ParticleThread*)data;
02727     ParticleThreadContext *ctx= thread->ctx;
02728     ParticleSystem *psys= ctx->sim.psys;
02729     ParticleCacheKey **cache= psys->childcache;
02730     ChildParticle *cpa;
02731     int i, totchild= ctx->totchild, first= 0;
02732 
02733     if(thread->tot > 1){
02734         first= ctx->parent_pass? 0 : ctx->totparent;
02735         totchild= ctx->parent_pass? ctx->totparent : ctx->totchild;
02736     }
02737     
02738     cpa= psys->child + first + thread->num;
02739     for(i=first+thread->num; i<totchild; i+=thread->tot, cpa+=thread->tot)
02740         psys_thread_create_path(thread, cpa, cache[i], i);
02741 
02742     return 0;
02743 }
02744 
02745 void psys_cache_child_paths(ParticleSimulationData *sim, float cfra, int editupdate)
02746 {
02747     ParticleThread *pthreads;
02748     ParticleThreadContext *ctx;
02749     ListBase threads;
02750     int i, totchild, totparent, totthread;
02751 
02752     if(sim->psys->flag & PSYS_GLOBAL_HAIR)
02753         return;
02754 
02755     pthreads= psys_threads_create(sim);
02756 
02757     if(!psys_threads_init_path(pthreads, sim->scene, cfra, editupdate)) {
02758         psys_threads_free(pthreads);
02759         return;
02760     }
02761 
02762     ctx= pthreads[0].ctx;
02763     totchild= ctx->totchild;
02764     totparent= ctx->totparent;
02765 
02766     if(editupdate && sim->psys->childcache && totchild == sim->psys->totchildcache) {
02767         ; /* just overwrite the existing cache */
02768     }
02769     else {
02770         /* clear out old and create new empty path cache */
02771         free_child_path_cache(sim->psys);
02772         sim->psys->childcache= psys_alloc_path_cache_buffers(&sim->psys->childcachebufs, totchild, ctx->steps+1);
02773         sim->psys->totchildcache = totchild;
02774     }
02775 
02776     totthread= pthreads[0].tot;
02777 
02778     if(totthread > 1) {
02779 
02780         /* make virtual child parents thread safe by calculating them first */
02781         if(totparent) {
02782             BLI_init_threads(&threads, exec_child_path_cache, totthread);
02783             
02784             for(i=0; i<totthread; i++) {
02785                 pthreads[i].ctx->parent_pass = 1;
02786                 BLI_insert_thread(&threads, &pthreads[i]);
02787             }
02788 
02789             BLI_end_threads(&threads);
02790 
02791             for(i=0; i<totthread; i++)
02792                 pthreads[i].ctx->parent_pass = 0;
02793         }
02794 
02795         BLI_init_threads(&threads, exec_child_path_cache, totthread);
02796 
02797         for(i=0; i<totthread; i++)
02798             BLI_insert_thread(&threads, &pthreads[i]);
02799 
02800         BLI_end_threads(&threads);
02801     }
02802     else
02803         exec_child_path_cache(&pthreads[0]);
02804 
02805     psys_threads_free(pthreads);
02806 }
02807 /* figure out incremental rotations along path starting from unit quat */
02808 static void cache_key_incremental_rotation(ParticleCacheKey *key0, ParticleCacheKey *key1, ParticleCacheKey *key2, float *prev_tangent, int i)
02809 {
02810     float cosangle, angle, tangent[3], normal[3], q[4];
02811 
02812     switch(i) {
02813     case 0:
02814         /* start from second key */
02815         break;
02816     case 1:
02817         /* calculate initial tangent for incremental rotations */
02818         sub_v3_v3v3(prev_tangent, key0->co, key1->co);
02819         normalize_v3(prev_tangent);
02820         unit_qt(key1->rot);
02821         break;
02822     default:
02823         sub_v3_v3v3(tangent, key0->co, key1->co);
02824         normalize_v3(tangent);
02825 
02826         cosangle= dot_v3v3(tangent, prev_tangent);
02827 
02828         /* note we do the comparison on cosangle instead of
02829         * angle, since floating point accuracy makes it give
02830         * different results across platforms */
02831         if(cosangle > 0.999999f) {
02832             copy_v4_v4(key1->rot, key2->rot);
02833         }
02834         else {
02835             angle= saacos(cosangle);
02836             cross_v3_v3v3(normal, prev_tangent, tangent);
02837             axis_angle_to_quat( q,normal, angle);
02838             mul_qt_qtqt(key1->rot, q, key2->rot);
02839         }
02840 
02841         copy_v3_v3(prev_tangent, tangent);
02842     }
02843 }
02844 /* Calculates paths ready for drawing/rendering.                                    */
02845 /* -Usefull for making use of opengl vertex arrays for super fast strand drawing.   */
02846 /* -Makes child strands possible and creates them too into the cache.               */
02847 /* -Cached path data is also used to determine cut position for the editmode tool.  */
02848 void psys_cache_paths(ParticleSimulationData *sim, float cfra)
02849 {
02850     PARTICLE_PSMD;
02851     ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
02852     ParticleSystem *psys = sim->psys;
02853     ParticleSettings *part = psys->part;
02854     ParticleCacheKey *ca, **cache;
02855 
02856     DerivedMesh *hair_dm = (psys->part->type==PART_HAIR && psys->flag & PSYS_HAIR_DYNAMICS) ? psys->hair_out_dm : NULL;
02857     
02858     ParticleKey result;
02859     
02860     Material *ma;
02861     ParticleInterpolationData pind;
02862     ParticleTexture ptex;
02863 
02864     PARTICLE_P;
02865     
02866     float birthtime = 0.0, dietime = 0.0;
02867     float t, time = 0.0, dfra = 1.0 /* , frs_sec = sim->scene->r.frs_sec*/ /*UNUSED*/;
02868     float col[4] = {0.5f, 0.5f, 0.5f, 1.0f};
02869     float prev_tangent[3] = {0.0f, 0.0f, 0.0f}, hairmat[4][4];
02870     float rotmat[3][3];
02871     int k;
02872     int steps = (int)pow(2.0, (double)(psys->renderdata ? part->ren_step : part->draw_step));
02873     int totpart = psys->totpart;
02874     float length, vec[3];
02875     float *vg_effector= NULL;
02876     float *vg_length= NULL, pa_length=1.0f;
02877     int keyed, baked;
02878 
02879     /* we don't have anything valid to create paths from so let's quit here */
02880     if((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache)==0)
02881         return;
02882 
02883     if(psys_in_edit_mode(sim->scene, psys))
02884         if(psys->renderdata==0 && (psys->edit==NULL || pset->flag & PE_DRAW_PART)==0)
02885             return;
02886 
02887     keyed = psys->flag & PSYS_KEYED;
02888     baked = psys->pointcache->mem_cache.first && psys->part->type != PART_HAIR;
02889 
02890     /* clear out old and create new empty path cache */
02891     psys_free_path_cache(psys, psys->edit);
02892     cache= psys->pathcache= psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, steps+1);
02893 
02894     psys->lattice = psys_get_lattice(sim);
02895     ma= give_current_material(sim->ob, psys->part->omat);
02896     if(ma && (psys->part->draw_col == PART_DRAW_COL_MAT))
02897         copy_v3_v3(col, &ma->r);
02898 
02899     if((psys->flag & PSYS_GLOBAL_HAIR)==0) {
02900         if((psys->part->flag & PART_CHILD_EFFECT)==0)
02901             vg_effector = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_EFFECTOR);
02902         
02903         if(!psys->totchild)
02904             vg_length = psys_cache_vgroup(psmd->dm, psys, PSYS_VG_LENGTH);
02905     }
02906 
02907     /*---first main loop: create all actual particles' paths---*/
02908     LOOP_SHOWN_PARTICLES {
02909         if(!psys->totchild) {
02910             psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.f);
02911             pa_length = ptex.length * (1.0f - part->randlength * PSYS_FRAND(psys->seed + p));
02912             if(vg_length)
02913                 pa_length *= psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_length);
02914         }
02915 
02916         pind.keyed = keyed;
02917         pind.cache = baked ? psys->pointcache : NULL;
02918         pind.epoint = NULL;
02919         pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
02920         pind.dm = hair_dm;
02921 
02922         memset(cache[p], 0, sizeof(*cache[p])*(steps+1));
02923 
02924         cache[p]->steps = steps;
02925 
02926         /*--get the first data points--*/
02927         init_particle_interpolation(sim->ob, sim->psys, pa, &pind);
02928 
02929         /* hairmat is needed for for non-hair particle too so we get proper rotations */
02930         psys_mat_hair_to_global(sim->ob, psmd->dm, psys->part->from, pa, hairmat);
02931         copy_v3_v3(rotmat[0], hairmat[2]);
02932         copy_v3_v3(rotmat[1], hairmat[1]);
02933         copy_v3_v3(rotmat[2], hairmat[0]);
02934 
02935         if(part->draw & PART_ABS_PATH_TIME) {
02936             birthtime = MAX2(pind.birthtime, part->path_start);
02937             dietime = MIN2(pind.dietime, part->path_end);
02938         }
02939         else {
02940             float tb = pind.birthtime;
02941             birthtime = tb + part->path_start * (pind.dietime - tb);
02942             dietime = tb + part->path_end * (pind.dietime - tb);
02943         }
02944 
02945         if(birthtime >= dietime) {
02946             cache[p]->steps = -1;
02947             continue;
02948         }
02949 
02950         dietime = birthtime + pa_length * (dietime - birthtime);
02951 
02952         /*--interpolate actual path from data points--*/
02953         for(k=0, ca=cache[p]; k<=steps; k++, ca++){
02954             time = (float)k / (float)steps;
02955             t = birthtime + time * (dietime - birthtime);
02956             result.time = -t;
02957             do_particle_interpolation(psys, p, pa, t, &pind, &result);
02958             copy_v3_v3(ca->co, result.co);
02959 
02960             /* dynamic hair is in object space */
02961             /* keyed and baked are already in global space */
02962             if(hair_dm)
02963                 mul_m4_v3(sim->ob->obmat, ca->co);
02964             else if(!keyed && !baked && !(psys->flag & PSYS_GLOBAL_HAIR))
02965                 mul_m4_v3(hairmat, ca->co);
02966 
02967             copy_v3_v3(ca->col, col);
02968         }
02969         
02970         /*--modify paths and calculate rotation & velocity--*/
02971 
02972         if(!(psys->flag & PSYS_GLOBAL_HAIR)) {
02973             /* apply effectors */
02974             if((psys->part->flag & PART_CHILD_EFFECT) == 0) {
02975                 float effector= 1.0f;
02976                 if(vg_effector)
02977                     effector*= psys_particle_value_from_verts(psmd->dm,psys->part->from,pa,vg_effector);
02978 
02979                 sub_v3_v3v3(vec,(cache[p]+1)->co,cache[p]->co);
02980                 length = len_v3(vec);
02981 
02982                 for(k=1, ca=cache[p]+1; k<=steps; k++, ca++)
02983                     do_path_effectors(sim, p, ca, k, steps, cache[p]->co, effector, dfra, cfra, &length, vec);
02984             }
02985 
02986             /* apply guide curves to path data */
02987             if(sim->psys->effectors && (psys->part->flag & PART_CHILD_EFFECT)==0) {
02988                 for(k=0, ca=cache[p]; k<=steps; k++, ca++)
02989                     /* ca is safe to cast, since only co and vel are used */
02990                     do_guides(sim->psys->effectors, (ParticleKey*)ca, p, (float)k/(float)steps);
02991             }
02992 
02993             /* lattices have to be calculated separately to avoid mixups between effector calculations */
02994             if(psys->lattice) {
02995                 for(k=0, ca=cache[p]; k<=steps; k++, ca++)
02996                     calc_latt_deform(psys->lattice, ca->co, 1.0f);
02997             }
02998         }
02999 
03000         /* finally do rotation & velocity */
03001         for(k=1, ca=cache[p]+1; k<=steps; k++, ca++) {
03002             cache_key_incremental_rotation(ca, ca - 1, ca - 2, prev_tangent, k);
03003 
03004             if(k == steps)
03005                 copy_qt_qt(ca->rot, (ca - 1)->rot);
03006 
03007             /* set velocity */
03008             sub_v3_v3v3(ca->vel, ca->co, (ca-1)->co);
03009 
03010             if(k==1)
03011                 copy_v3_v3((ca-1)->vel, ca->vel);
03012         }
03013         /* First rotation is based on emitting face orientation.
03014          * This is way better than having flipping rotations resulting
03015          * from using a global axis as a rotation pole (vec_to_quat()).
03016          * It's not an ideal solution though since it disregards the
03017          * initial tangent, but taking that in to account will allow
03018          * the possibility of flipping again. -jahka
03019          */
03020         mat3_to_quat_is_ok(cache[p]->rot, rotmat);
03021     }
03022 
03023     psys->totcached = totpart;
03024 
03025     if(psys->lattice){
03026         end_latt_deform(psys->lattice);
03027         psys->lattice= NULL;
03028     }
03029 
03030     if(vg_effector)
03031         MEM_freeN(vg_effector);
03032 
03033     if(vg_length)
03034         MEM_freeN(vg_length);
03035 }
03036 void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cfra)
03037 {
03038     ParticleCacheKey *ca, **cache= edit->pathcache;
03039     ParticleEditSettings *pset = &scene->toolsettings->particle;
03040     
03041     PTCacheEditPoint *point = NULL;
03042     PTCacheEditKey *ekey = NULL;
03043 
03044     ParticleSystem *psys = edit->psys;
03045     ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
03046     ParticleData *pa = psys ? psys->particles : NULL;
03047 
03048     ParticleInterpolationData pind;
03049     ParticleKey result;
03050     
03051     float birthtime = 0.0f, dietime = 0.0f;
03052     float t, time = 0.0f, keytime = 0.0f /*, frs_sec */;
03053     float hairmat[4][4], rotmat[3][3], prev_tangent[3] = {0.0f, 0.0f, 0.0f};
03054     int k, i;
03055     int steps = (int)pow(2.0, (double)pset->draw_step);
03056     int totpart = edit->totpoint, recalc_set=0;
03057     float sel_col[3];
03058     float nosel_col[3];
03059 
03060     steps = MAX2(steps, 4);
03061 
03062     if(!cache || edit->totpoint != edit->totcached) {
03063         /* clear out old and create new empty path cache */
03064         psys_free_path_cache(edit->psys, edit);
03065         cache= edit->pathcache= psys_alloc_path_cache_buffers(&edit->pathcachebufs, totpart, steps+1);
03066 
03067         /* set flag for update (child particles check this too) */
03068         for(i=0, point=edit->points; i<totpart; i++, point++)
03069             point->flag |= PEP_EDIT_RECALC;
03070         recalc_set = 1;
03071     }
03072 
03073     /* frs_sec = (psys || edit->pid.flag & PTCACHE_VEL_PER_SEC) ? 25.0f : 1.0f; */ /* UNUSED */
03074 
03075     if(pset->brushtype == PE_BRUSH_WEIGHT) {
03076         ;/* use weight painting colors now... */
03077     }
03078     else{
03079         sel_col[0] = (float)edit->sel_col[0] / 255.0f;
03080         sel_col[1] = (float)edit->sel_col[1] / 255.0f;
03081         sel_col[2] = (float)edit->sel_col[2] / 255.0f;
03082         nosel_col[0] = (float)edit->nosel_col[0] / 255.0f;
03083         nosel_col[1] = (float)edit->nosel_col[1] / 255.0f;
03084         nosel_col[2] = (float)edit->nosel_col[2] / 255.0f;
03085     }
03086 
03087     /*---first main loop: create all actual particles' paths---*/
03088     for(i=0, point=edit->points; i<totpart; i++, pa+=pa?1:0, point++){
03089         if(edit->totcached && !(point->flag & PEP_EDIT_RECALC))
03090             continue;
03091 
03092         ekey = point->keys;
03093 
03094         pind.keyed = 0;
03095         pind.cache = NULL;
03096         pind.epoint = point;
03097         pind.bspline = psys ? (psys->part->flag & PART_HAIR_BSPLINE) : 0;
03098         pind.dm = NULL;
03099 
03100 
03101         /* should init_particle_interpolation set this ? */
03102         if(pset->brushtype==PE_BRUSH_WEIGHT){
03103             pind.hkey[0] = NULL;
03104             /* pa != NULL since the weight brush is only available for hair */
03105             pind.hkey[1] = pa->hair;
03106         }
03107 
03108 
03109         memset(cache[i], 0, sizeof(*cache[i])*(steps+1));
03110 
03111         cache[i]->steps = steps;
03112 
03113         /*--get the first data points--*/
03114         init_particle_interpolation(ob, psys, pa, &pind);
03115 
03116         if(psys) {
03117             psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
03118             copy_v3_v3(rotmat[0], hairmat[2]);
03119             copy_v3_v3(rotmat[1], hairmat[1]);
03120             copy_v3_v3(rotmat[2], hairmat[0]);
03121         }
03122 
03123         birthtime = pind.birthtime;
03124         dietime = pind.dietime;
03125 
03126         if(birthtime >= dietime) {
03127             cache[i]->steps = -1;
03128             continue;
03129         }
03130 
03131         /*--interpolate actual path from data points--*/
03132         for(k=0, ca=cache[i]; k<=steps; k++, ca++){
03133             time = (float)k / (float)steps;
03134             t = birthtime + time * (dietime - birthtime);
03135             result.time = -t;
03136             do_particle_interpolation(psys, i, pa, t, &pind, &result);
03137             copy_v3_v3(ca->co, result.co);
03138 
03139              /* non-hair points are already in global space */
03140             if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
03141                 mul_m4_v3(hairmat, ca->co);
03142 
03143                 if(k) {
03144                     cache_key_incremental_rotation(ca, ca - 1, ca - 2, prev_tangent, k);
03145 
03146                     if(k == steps)
03147                         copy_qt_qt(ca->rot, (ca - 1)->rot);
03148 
03149                     /* set velocity */
03150                     sub_v3_v3v3(ca->vel, ca->co, (ca - 1)->co);
03151 
03152                     if(k==1)
03153                         copy_v3_v3((ca - 1)->vel, ca->vel);
03154                 }
03155             }
03156             else {
03157                 ca->vel[0] = ca->vel[1] = 0.0f;
03158                 ca->vel[2] = 1.0f;
03159             }
03160 
03161             /* selection coloring in edit mode */
03162             if(pset->brushtype==PE_BRUSH_WEIGHT){
03163                 float t2;
03164 
03165                 if(k==0) {
03166                     weight_to_rgb(ca->col, pind.hkey[1]->weight);
03167                 } else {
03168                     float w1[3], w2[3];
03169                     keytime = (t - (*pind.ekey[0]->time))/((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
03170 
03171                     weight_to_rgb(w1, pind.hkey[0]->weight);
03172                     weight_to_rgb(w2, pind.hkey[1]->weight);
03173 
03174                     interp_v3_v3v3(ca->col, w1, w2, keytime);
03175                 }
03176 
03177                 /* at the moment this is only used for weight painting.
03178                  * will need to move out of this check if its used elsewhere. */
03179                 t2 = birthtime + ((float)k/(float)steps) * (dietime - birthtime);
03180 
03181                 while (pind.hkey[1]->time < t2) pind.hkey[1]++;
03182                 pind.hkey[0] = pind.hkey[1] - 1;
03183             }
03184             else {
03185                 if((ekey + (pind.ekey[0] - point->keys))->flag & PEK_SELECT){
03186                     if((ekey + (pind.ekey[1] - point->keys))->flag & PEK_SELECT){
03187                         copy_v3_v3(ca->col, sel_col);
03188                     }
03189                     else{
03190                         keytime = (t - (*pind.ekey[0]->time))/((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
03191                         interp_v3_v3v3(ca->col, sel_col, nosel_col, keytime);
03192                     }
03193                 }
03194                 else{
03195                     if((ekey + (pind.ekey[1] - point->keys))->flag & PEK_SELECT){
03196                         keytime = (t - (*pind.ekey[0]->time))/((*pind.ekey[1]->time) - (*pind.ekey[0]->time));
03197                         interp_v3_v3v3(ca->col, nosel_col, sel_col, keytime);
03198                     }
03199                     else{
03200                         copy_v3_v3(ca->col, nosel_col);
03201                     }
03202                 }
03203             }
03204 
03205             ca->time = t;
03206         }
03207         if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
03208             /* First rotation is based on emitting face orientation.
03209              * This is way better than having flipping rotations resulting
03210              * from using a global axis as a rotation pole (vec_to_quat()).
03211              * It's not an ideal solution though since it disregards the
03212              * initial tangent, but taking that in to account will allow
03213              * the possibility of flipping again. -jahka
03214              */
03215             mat3_to_quat_is_ok(cache[i]->rot, rotmat);
03216         }
03217     }
03218 
03219     edit->totcached = totpart;
03220 
03221     if(psys) {
03222         ParticleSimulationData sim= {0};
03223         sim.scene= scene;
03224         sim.ob= ob;
03225         sim.psys= psys;
03226         sim.psmd= psys_get_modifier(ob, psys);
03227 
03228         psys_cache_child_paths(&sim, cfra, 1);
03229     }
03230 
03231     /* clear recalc flag if set here */
03232     if(recalc_set) {
03233         for(i=0, point=edit->points; i<totpart; i++, point++)
03234             point->flag &= ~PEP_EDIT_RECALC;
03235     }
03236 }
03237 /************************************************/
03238 /*          Particle Key handling               */
03239 /************************************************/
03240 void copy_particle_key(ParticleKey *to, ParticleKey *from, int time)
03241 {
03242     if(time){
03243         memcpy(to,from,sizeof(ParticleKey));
03244     }
03245     else{
03246         float to_time=to->time;
03247         memcpy(to,from,sizeof(ParticleKey));
03248         to->time=to_time;
03249     }
03250 }
03251 void psys_get_from_key(ParticleKey *key, float *loc, float *vel, float *rot, float *time)
03252 {
03253     if(loc) copy_v3_v3(loc,key->co);
03254     if(vel) copy_v3_v3(vel,key->vel);
03255     if(rot) copy_qt_qt(rot,key->rot);
03256     if(time) *time=key->time;
03257 }
03258 /*-------changing particle keys from space to another-------*/
03259 #if 0
03260 static void key_from_object(Object *ob, ParticleKey *key)
03261 {
03262     float q[4];
03263 
03264     add_v3_v3(key->vel, key->co);
03265 
03266     mul_m4_v3(ob->obmat,key->co);
03267     mul_m4_v3(ob->obmat,key->vel);
03268     mat4_to_quat(q,ob->obmat);
03269 
03270     sub_v3_v3v3(key->vel,key->vel,key->co);
03271     mul_qt_qtqt(key->rot,q,key->rot);
03272 }
03273 #endif
03274 
03275 static void triatomat(float *v1, float *v2, float *v3, float (*uv)[2], float mat[][4])
03276 {
03277     float det, w1, w2, d1[2], d2[2];
03278 
03279     memset(mat, 0, sizeof(float)*4*4);
03280     mat[3][3]= 1.0f;
03281 
03282     /* first axis is the normal */
03283     normal_tri_v3( mat[2],v1, v2, v3);
03284 
03285     /* second axis along (1, 0) in uv space */
03286     if(uv) {
03287         d1[0]= uv[1][0] - uv[0][0];
03288         d1[1]= uv[1][1] - uv[0][1];
03289         d2[0]= uv[2][0] - uv[0][0];
03290         d2[1]= uv[2][1] - uv[0][1];
03291 
03292         det = d2[0]*d1[1] - d2[1]*d1[0];
03293 
03294         if(det != 0.0f) {
03295             det= 1.0f/det;
03296             w1= -d2[1]*det;
03297             w2= d1[1]*det;
03298 
03299             mat[1][0]= w1*(v2[0] - v1[0]) + w2*(v3[0] - v1[0]);
03300             mat[1][1]= w1*(v2[1] - v1[1]) + w2*(v3[1] - v1[1]);
03301             mat[1][2]= w1*(v2[2] - v1[2]) + w2*(v3[2] - v1[2]);
03302             normalize_v3(mat[1]);
03303         }
03304         else
03305             mat[1][0]= mat[1][1]= mat[1][2]= 0.0f;
03306     }
03307     else {
03308         sub_v3_v3v3(mat[1], v2, v1);
03309         normalize_v3(mat[1]);
03310     }
03311     
03312     /* third as a cross product */
03313     cross_v3_v3v3(mat[0], mat[1], mat[2]);
03314 }
03315 
03316 static void psys_face_mat(Object *ob, DerivedMesh *dm, ParticleData *pa, float mat[][4], int orco)
03317 {
03318     float v[3][3];
03319     MFace *mface;
03320     OrigSpaceFace *osface;
03321     float (*orcodata)[3];
03322 
03323     int i = pa->num_dmcache==DMCACHE_NOTFOUND ? pa->num : pa->num_dmcache;
03324     
03325     if (i==-1 || i >= dm->getNumFaces(dm)) { unit_m4(mat); return; }
03326 
03327     mface=dm->getFaceData(dm,i,CD_MFACE);
03328     osface=dm->getFaceData(dm,i,CD_ORIGSPACE);
03329     
03330     if(orco && (orcodata=dm->getVertDataArray(dm, CD_ORCO))) {
03331         copy_v3_v3(v[0], orcodata[mface->v1]);
03332         copy_v3_v3(v[1], orcodata[mface->v2]);
03333         copy_v3_v3(v[2], orcodata[mface->v3]);
03334 
03335         /* ugly hack to use non-transformed orcos, since only those
03336          * give symmetric results for mirroring in particle mode */
03337         if(DM_get_vert_data_layer(dm, CD_ORIGINDEX))
03338             transform_mesh_orco_verts(ob->data, v, 3, 1);
03339     }
03340     else {
03341         dm->getVertCo(dm,mface->v1,v[0]);
03342         dm->getVertCo(dm,mface->v2,v[1]);
03343         dm->getVertCo(dm,mface->v3,v[2]);
03344     }
03345 
03346     triatomat(v[0], v[1], v[2], (osface)? osface->uv: NULL, mat);
03347 }
03348 
03349 void psys_mat_hair_to_object(Object *UNUSED(ob), DerivedMesh *dm, short from, ParticleData *pa, float hairmat[][4])
03350 {
03351     float vec[3];
03352 
03353     psys_face_mat(0, dm, pa, hairmat, 0);
03354     psys_particle_on_dm(dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, 0, 0);
03355     copy_v3_v3(hairmat[3],vec);
03356 }
03357 
03358 void psys_mat_hair_to_orco(Object *ob, DerivedMesh *dm, short from, ParticleData *pa, float hairmat[][4])
03359 {
03360     float vec[3], orco[3];
03361 
03362     psys_face_mat(ob, dm, pa, hairmat, 1);
03363     psys_particle_on_dm(dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, orco, 0);
03364 
03365     /* see psys_face_mat for why this function is called */
03366     if(DM_get_vert_data_layer(dm, CD_ORIGINDEX))
03367         transform_mesh_orco_verts(ob->data, &orco, 1, 1);
03368     copy_v3_v3(hairmat[3],orco);
03369 }
03370 
03371 void psys_vec_rot_to_face(DerivedMesh *dm, ParticleData *pa, float *vec)
03372 {
03373     float mat[4][4];
03374 
03375     psys_face_mat(0, dm, pa, mat, 0);
03376     transpose_m4(mat); /* cheap inverse for rotation matrix */
03377     mul_mat3_m4_v3(mat, vec);
03378 }
03379 
03380 void psys_mat_hair_to_global(Object *ob, DerivedMesh *dm, short from, ParticleData *pa, float hairmat[][4])
03381 {
03382     float facemat[4][4];
03383 
03384     psys_mat_hair_to_object(ob, dm, from, pa, facemat);
03385 
03386     mult_m4_m4m4(hairmat, ob->obmat, facemat);
03387 }
03388 
03389 /************************************************/
03390 /*          ParticleSettings handling           */
03391 /************************************************/
03392 ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *name)
03393 {
03394     ParticleSystem *psys;
03395     ModifierData *md;
03396     ParticleSystemModifierData *psmd;
03397 
03398     if(!ob || ob->type != OB_MESH)
03399         return NULL;
03400 
03401     psys = ob->particlesystem.first;
03402     for(; psys; psys=psys->next)
03403         psys->flag &= ~PSYS_CURRENT;
03404 
03405     psys = MEM_callocN(sizeof(ParticleSystem), "particle_system");
03406     psys->pointcache = BKE_ptcache_add(&psys->ptcaches);
03407     BLI_addtail(&ob->particlesystem, psys);
03408 
03409     psys->part = psys_new_settings("ParticleSettings", NULL);
03410 
03411     if(BLI_countlist(&ob->particlesystem)>1)
03412         BLI_snprintf(psys->name, sizeof(psys->name), "ParticleSystem %i", BLI_countlist(&ob->particlesystem));
03413     else
03414         strcpy(psys->name, "ParticleSystem");
03415 
03416     md= modifier_new(eModifierType_ParticleSystem);
03417 
03418     if(name)    BLI_strncpy(md->name, name, sizeof(md->name));
03419     else        BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", BLI_countlist(&ob->particlesystem));
03420     modifier_unique_name(&ob->modifiers, md);
03421 
03422     psmd= (ParticleSystemModifierData*) md;
03423     psmd->psys=psys;
03424     BLI_addtail(&ob->modifiers, md);
03425 
03426     psys->totpart=0;
03427     psys->flag = PSYS_ENABLED|PSYS_CURRENT;
03428     psys->cfra = BKE_frame_to_ctime(scene, CFRA + 1);
03429 
03430     DAG_scene_sort(G.main, scene);
03431     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
03432 
03433     return md;
03434 }
03435 void object_remove_particle_system(Scene *scene, Object *ob)
03436 {
03437     ParticleSystem *psys = psys_get_current(ob);
03438     ParticleSystemModifierData *psmd;
03439     ModifierData *md;
03440 
03441     if(!psys)
03442         return;
03443 
03444     /* clear all other appearances of this pointer (like on smoke flow modifier) */
03445     if((md = modifiers_findByType(ob, eModifierType_Smoke)))
03446     {
03447         SmokeModifierData *smd = (SmokeModifierData *)md;
03448         if((smd->type == MOD_SMOKE_TYPE_FLOW) && smd->flow && smd->flow->psys)
03449             if(smd->flow->psys == psys)
03450                 smd->flow->psys = NULL;
03451     }
03452 
03453     if((md = modifiers_findByType(ob, eModifierType_DynamicPaint)))
03454     {
03455         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md;
03456         if(pmd->brush && pmd->brush->psys)
03457             if(pmd->brush->psys == psys)
03458                 pmd->brush->psys = NULL;
03459     }
03460 
03461     /* clear modifier */
03462     psmd= psys_get_modifier(ob, psys);
03463     BLI_remlink(&ob->modifiers, psmd);
03464     modifier_free((ModifierData *)psmd);
03465 
03466     /* clear particle system */
03467     BLI_remlink(&ob->particlesystem, psys);
03468     psys_free(ob,psys);
03469 
03470     if(ob->particlesystem.first)
03471         ((ParticleSystem *) ob->particlesystem.first)->flag |= PSYS_CURRENT;
03472     else
03473         ob->mode &= ~OB_MODE_PARTICLE_EDIT;
03474 
03475     DAG_scene_sort(G.main, scene);
03476     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
03477 }
03478 static void default_particle_settings(ParticleSettings *part)
03479 {
03480     part->type= PART_EMITTER;
03481     part->distr= PART_DISTR_JIT;
03482     part->draw_as = PART_DRAW_REND;
03483     part->ren_as = PART_DRAW_HALO;
03484     part->bb_uv_split=1;
03485     part->bb_align=PART_BB_VIEW;
03486     part->bb_split_offset=PART_BB_OFF_LINEAR;
03487     part->flag=PART_EDISTR|PART_TRAND|PART_HIDE_ADVANCED_HAIR;
03488 
03489     part->sta= 1.0;
03490     part->end= 200.0;
03491     part->lifetime= 50.0;
03492     part->jitfac= 1.0;
03493     part->totpart= 1000;
03494     part->grid_res= 10;
03495     part->timetweak= 1.0;
03496     part->courant_target = 0.2;
03497     
03498     part->integrator= PART_INT_MIDPOINT;
03499     part->phystype= PART_PHYS_NEWTON;
03500     part->hair_step= 5;
03501     part->keys_step= 5;
03502     part->draw_step= 2;
03503     part->ren_step= 3;
03504     part->adapt_angle= 5;
03505     part->adapt_pix= 3;
03506     part->kink_axis= 2;
03507     part->kink_amp_clump= 1.f;
03508     part->reactevent= PART_EVENT_DEATH;
03509     part->disp=100;
03510     part->from= PART_FROM_FACE;
03511 
03512     part->normfac= 1.0f;
03513 
03514     part->mass=1.0;
03515     part->size=0.05;
03516     part->childsize=1.0;
03517 
03518     part->rotmode = PART_ROT_VEL;
03519     part->avemode = PART_AVE_SPIN;
03520 
03521     part->child_nbr=10;
03522     part->ren_child_nbr=100;
03523     part->childrad=0.2f;
03524     part->childflat=0.0f;
03525     part->clumppow=0.0f;
03526     part->kink_amp=0.2f;
03527     part->kink_freq=2.0;
03528 
03529     part->rough1_size=1.0;
03530     part->rough2_size=1.0;
03531     part->rough_end_shape=1.0;
03532 
03533     part->clength=1.0f;
03534     part->clength_thres=0.0f;
03535 
03536     part->draw= PART_DRAW_EMITTER;
03537     part->draw_line[0]=0.5;
03538     part->path_start = 0.0f;
03539     part->path_end = 1.0f;
03540 
03541     part->bb_size[0] = part->bb_size[1] = 1.0f;
03542 
03543     part->keyed_loops = 1;
03544 
03545     part->color_vec_max = 1.f;
03546     part->draw_col = PART_DRAW_COL_MAT;
03547 
03548     part->simplify_refsize= 1920;
03549     part->simplify_rate= 1.0f;
03550     part->simplify_transition= 0.1f;
03551     part->simplify_viewport= 0.8;
03552 
03553     if(!part->effector_weights)
03554         part->effector_weights = BKE_add_effector_weights(NULL);
03555 }
03556 
03557 
03558 ParticleSettings *psys_new_settings(const char *name, Main *main)
03559 {
03560     ParticleSettings *part;
03561 
03562     if(main==NULL)
03563         main = G.main;
03564 
03565     part= alloc_libblock(&main->particle, ID_PA, name);
03566     
03567     default_particle_settings(part);
03568 
03569     return part;
03570 }
03571 
03572 ParticleSettings *psys_copy_settings(ParticleSettings *part)
03573 {
03574     ParticleSettings *partn;
03575     int a;
03576 
03577     partn= copy_libblock(&part->id);
03578     partn->pd= MEM_dupallocN(part->pd);
03579     partn->pd2= MEM_dupallocN(part->pd2);
03580     partn->effector_weights= MEM_dupallocN(part->effector_weights);
03581     partn->fluid= MEM_dupallocN(part->fluid);
03582 
03583     partn->boids = boid_copy_settings(part->boids);
03584 
03585     for(a=0; a<MAX_MTEX; a++) {
03586         if(part->mtex[a]) {
03587             partn->mtex[a]= MEM_mallocN(sizeof(MTex), "psys_copy_tex");
03588             memcpy(partn->mtex[a], part->mtex[a], sizeof(MTex));
03589             id_us_plus((ID *)partn->mtex[a]->tex);
03590         }
03591     }
03592 
03593     BLI_duplicatelist(&partn->dupliweights, &part->dupliweights);
03594     
03595     return partn;
03596 }
03597 
03598 static void expand_local_particlesettings(ParticleSettings *part)
03599 {
03600     int i;
03601     id_lib_extern((ID *)part->dup_group);
03602 
03603     for(i=0; i<MAX_MTEX; i++) {
03604         if(part->mtex[i]) id_lib_extern((ID *)part->mtex[i]->tex);
03605     }
03606 }
03607 
03608 void make_local_particlesettings(ParticleSettings *part)
03609 {
03610     Main *bmain= G.main;
03611     Object *ob;
03612     int is_local= FALSE, is_lib= FALSE;
03613 
03614     /* - only lib users: do nothing
03615      * - only local users: set flag
03616      * - mixed: make copy
03617      */
03618     
03619     if(part->id.lib==0) return;
03620     if(part->id.us==1) {
03621         id_clear_lib_data(bmain, &part->id);
03622         expand_local_particlesettings(part);
03623         return;
03624     }
03625 
03626     /* test objects */
03627     for(ob= bmain->object.first; ob && ELEM(FALSE, is_lib, is_local); ob= ob->id.next) {
03628         ParticleSystem *psys=ob->particlesystem.first;
03629         for(; psys; psys=psys->next){
03630             if(psys->part==part) {
03631                 if(ob->id.lib) is_lib= TRUE;
03632                 else is_local= TRUE;
03633             }
03634         }
03635     }
03636     
03637     if(is_local && is_lib==FALSE) {
03638         id_clear_lib_data(bmain, &part->id);
03639         expand_local_particlesettings(part);
03640     }
03641     else if(is_local && is_lib) {
03642         ParticleSettings *part_new= psys_copy_settings(part);
03643 
03644         part_new->id.us= 0;
03645 
03646         /* Remap paths of new ID using old library as base. */
03647         BKE_id_lib_local_paths(bmain, part->id.lib, &part_new->id);
03648 
03649         /* do objects */
03650         for(ob= bmain->object.first; ob; ob= ob->id.next) {
03651             ParticleSystem *psys;
03652             for(psys= ob->particlesystem.first; psys; psys=psys->next){
03653                 if(psys->part==part && ob->id.lib==0) {
03654                     psys->part= part_new;
03655                     part_new->id.us++;
03656                     part->id.us--;
03657                 }
03658             }
03659         }
03660     }
03661 }
03662 
03663 /************************************************/
03664 /*          Textures                            */
03665 /************************************************/
03666 
03667 static int get_particle_uv(DerivedMesh *dm, ParticleData *pa, int face_index, const float fuv[4], char *name, float *texco)
03668 {
03669     MFace *mf;
03670     MTFace *tf;
03671     int i;
03672     
03673     tf= CustomData_get_layer_named(&dm->faceData, CD_MTFACE, name);
03674 
03675     if(tf == NULL)
03676         tf= CustomData_get_layer(&dm->faceData, CD_MTFACE);
03677 
03678     if(tf == NULL)
03679         return 0;
03680 
03681     if(pa) {
03682         i= (pa->num_dmcache==DMCACHE_NOTFOUND)? pa->num: pa->num_dmcache;
03683         if(i >= dm->getNumFaces(dm))
03684             i = -1;
03685     }
03686     else
03687         i= face_index;
03688 
03689     if (i==-1) {
03690         texco[0]= 0.0f;
03691         texco[1]= 0.0f;
03692         texco[2]= 0.0f;
03693     }
03694     else {
03695         mf= dm->getFaceData(dm, i, CD_MFACE);
03696 
03697         psys_interpolate_uvs(&tf[i], mf->v4, fuv, texco);
03698 
03699         texco[0]= texco[0]*2.0f - 1.0f;
03700         texco[1]= texco[1]*2.0f - 1.0f;
03701         texco[2]= 0.0f;
03702     }
03703 
03704     return 1;
03705 }
03706 
03707 #define SET_PARTICLE_TEXTURE(type, pvalue, texfac) if((event & mtex->mapto) & type) {pvalue = texture_value_blend(def, pvalue, value, texfac, blend);}
03708 #define CLAMP_PARTICLE_TEXTURE_POS(type, pvalue) if(event & type) { if(pvalue < 0.f) pvalue = 1.f+pvalue; CLAMP(pvalue, 0.0f, 1.0f); }
03709 #define CLAMP_PARTICLE_TEXTURE_POSNEG(type, pvalue) if(event & type) { CLAMP(pvalue, -1.0f, 1.0f); }
03710 
03711 static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSettings *part, ParticleData *par, int child_index, int face_index, const float fw[4], float *orco, ParticleTexture *ptex, int event, float cfra)
03712 {
03713     MTex *mtex, **mtexp = part->mtex;
03714     int m;
03715     float value, rgba[4], texvec[3];
03716 
03717     ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp =
03718         ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink =
03719         ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.f;
03720 
03721     ptex->length= 1.0f - part->randlength * PSYS_FRAND(child_index + 26);
03722     ptex->length*= part->clength_thres < PSYS_FRAND(child_index + 27) ? part->clength : 1.0f;
03723 
03724     for(m=0; m<MAX_MTEX; m++, mtexp++){
03725         mtex = *mtexp;
03726         if(mtex && mtex->mapto){
03727             float def=mtex->def_var;
03728             short blend=mtex->blendtype;
03729             short texco = mtex->texco;
03730 
03731             if(ELEM(texco, TEXCO_UV, TEXCO_ORCO) && (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME) == 0 || part->distr == PART_DISTR_GRID))
03732                 texco = TEXCO_GLOB;
03733 
03734             switch(texco) {
03735             case TEXCO_GLOB:
03736                 copy_v3_v3(texvec, par->state.co);
03737                 break;
03738             case TEXCO_OBJECT:
03739                 copy_v3_v3(texvec, par->state.co);
03740                 if(mtex->object)
03741                     mul_m4_v3(mtex->object->imat, texvec);
03742                 break;
03743             case TEXCO_UV:
03744                 if(fw && get_particle_uv(dm, NULL, face_index, fw, mtex->uvname, texvec))
03745                     break;
03746                 /* no break, failed to get uv's, so let's try orco's */
03747             case TEXCO_ORCO:
03748                 copy_v3_v3(texvec, orco);
03749                 break;
03750             case TEXCO_PARTICLE:
03751                 /* texture coordinates in range [-1,1] */
03752                 texvec[0] = 2.f * (cfra - par->time)/(par->dietime-par->time) - 1.f;
03753                 texvec[1] = 0.f;
03754                 texvec[2] = 0.f;
03755                 break;
03756             }
03757 
03758             externtex(mtex, texvec, &value, rgba, rgba+1, rgba+2, rgba+3, 0);
03759 
03760             if((event & mtex->mapto) & PAMAP_ROUGH)
03761                 ptex->rough1= ptex->rough2= ptex->roughe= texture_value_blend(def,ptex->rough1,value,mtex->roughfac,blend);
03762 
03763             SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac);
03764             SET_PARTICLE_TEXTURE(PAMAP_CLUMP, ptex->clump, mtex->clumpfac);
03765             SET_PARTICLE_TEXTURE(PAMAP_KINK, ptex->kink, mtex->kinkfac);
03766             SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac);
03767         }
03768     }
03769 
03770     CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LENGTH, ptex->length);
03771     CLAMP_PARTICLE_TEXTURE_POS(PAMAP_CLUMP, ptex->clump);
03772     CLAMP_PARTICLE_TEXTURE_POS(PAMAP_KINK, ptex->kink);
03773     CLAMP_PARTICLE_TEXTURE_POS(PAMAP_ROUGH, ptex->rough1);
03774     CLAMP_PARTICLE_TEXTURE_POS(PAMAP_DENS, ptex->exist);
03775 }
03776 void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTexture *ptex, int event, float cfra)
03777 {
03778     ParticleSettings *part = sim->psys->part;
03779     MTex **mtexp = part->mtex;
03780     MTex *mtex;
03781     int m;
03782     float value, rgba[4], co[3], texvec[3];
03783     int setvars=0;
03784 
03785     /* initialize ptex */
03786     ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp =
03787         ptex->gravity = ptex->field = ptex->length = ptex->clump = ptex->kink =
03788         ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.f;
03789 
03790     ptex->time = (float)(pa - sim->psys->particles)/(float)sim->psys->totpart;
03791 
03792     for(m=0; m<MAX_MTEX; m++, mtexp++){
03793         mtex = *mtexp;
03794         if(mtex && mtex->mapto){
03795             float def=mtex->def_var;
03796             short blend=mtex->blendtype;
03797             short texco = mtex->texco;
03798 
03799             if(texco == TEXCO_UV && (ELEM(part->from, PART_FROM_FACE, PART_FROM_VOLUME) == 0 || part->distr == PART_DISTR_GRID))
03800                 texco = TEXCO_GLOB;
03801 
03802             switch(texco) {
03803             case TEXCO_GLOB:
03804                 copy_v3_v3(texvec, pa->state.co);
03805                 break;
03806             case TEXCO_OBJECT:
03807                 copy_v3_v3(texvec, pa->state.co);
03808                 if(mtex->object)
03809                     mul_m4_v3(mtex->object->imat, texvec);
03810                 break;
03811             case TEXCO_UV:
03812                 if(get_particle_uv(sim->psmd->dm, pa, 0, pa->fuv, mtex->uvname, texvec))
03813                     break;
03814                 /* no break, failed to get uv's, so let's try orco's */
03815             case TEXCO_ORCO:
03816                 psys_particle_on_emitter(sim->psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,texvec, 0);
03817                 break;
03818             case TEXCO_PARTICLE:
03819                 /* texture coordinates in range [-1,1] */
03820                 texvec[0] = 2.f * (cfra - pa->time)/(pa->dietime-pa->time) - 1.f;
03821                 texvec[1] = 0.f;
03822                 texvec[2] = 0.f;
03823                 break;
03824             }
03825 
03826             externtex(mtex, texvec, &value, rgba, rgba+1, rgba+2, rgba+3, 0);
03827 
03828             if((event & mtex->mapto) & PAMAP_TIME) {
03829                 /* the first time has to set the base value for time regardless of blend mode */
03830                 if((setvars&MAP_PA_TIME)==0){
03831                     int flip= (mtex->timefac < 0.0f);
03832                     float timefac= fabsf(mtex->timefac);
03833                     ptex->time *= 1.0f - timefac;
03834                     ptex->time += timefac * ((flip)? 1.0f - value : value);
03835                     setvars |= MAP_PA_TIME;
03836                 }
03837                 else
03838                     ptex->time= texture_value_blend(def,ptex->time,value,mtex->timefac,blend);
03839             }
03840             SET_PARTICLE_TEXTURE(PAMAP_LIFE, ptex->life, mtex->lifefac)
03841             SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac)
03842             SET_PARTICLE_TEXTURE(PAMAP_SIZE, ptex->size, mtex->sizefac)
03843             SET_PARTICLE_TEXTURE(PAMAP_IVEL, ptex->ivel, mtex->ivelfac)
03844             SET_PARTICLE_TEXTURE(PAMAP_FIELD, ptex->field, mtex->fieldfac)
03845             SET_PARTICLE_TEXTURE(PAMAP_GRAVITY, ptex->gravity, mtex->gravityfac)
03846             SET_PARTICLE_TEXTURE(PAMAP_DAMP, ptex->damp, mtex->dampfac)
03847             SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac)
03848         }
03849     }
03850 
03851     CLAMP_PARTICLE_TEXTURE_POS(PAMAP_TIME, ptex->time)
03852     CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LIFE, ptex->life)
03853     CLAMP_PARTICLE_TEXTURE_POS(PAMAP_DENS, ptex->exist)
03854     CLAMP_PARTICLE_TEXTURE_POS(PAMAP_SIZE, ptex->size)
03855     CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_IVEL, ptex->ivel)
03856     CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_FIELD, ptex->field)
03857     CLAMP_PARTICLE_TEXTURE_POSNEG(PAMAP_GRAVITY, ptex->gravity)
03858     CLAMP_PARTICLE_TEXTURE_POS(PAMAP_DAMP, ptex->damp)
03859     CLAMP_PARTICLE_TEXTURE_POS(PAMAP_LENGTH, ptex->length)
03860 }
03861 /************************************************/
03862 /*          Particle State                      */
03863 /************************************************/
03864 float psys_get_timestep(ParticleSimulationData *sim)
03865 {
03866     return 0.04f * sim->psys->part->timetweak;
03867 }
03868 float psys_get_child_time(ParticleSystem *psys, ChildParticle *cpa, float cfra, float *birthtime, float *dietime)
03869 {
03870     ParticleSettings *part = psys->part;
03871     float time, life;
03872 
03873     if(part->childtype==PART_CHILD_FACES){
03874         int w=0;
03875         time=0.0;
03876         while(w<4 && cpa->pa[w]>=0){
03877             time+=cpa->w[w]*(psys->particles+cpa->pa[w])->time;
03878             w++;
03879         }
03880 
03881         life = part->lifetime * (1.0f - part->randlife * PSYS_FRAND(cpa - psys->child + 25));
03882     }
03883     else{
03884         ParticleData *pa = psys->particles + cpa->parent;
03885 
03886         time = pa->time;
03887         life = pa->lifetime;
03888     }
03889 
03890     if(birthtime)
03891         *birthtime = time;
03892     if(dietime)
03893         *dietime = time+life;
03894 
03895     return (cfra-time)/life;
03896 }
03897 float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float UNUSED(cfra), float *UNUSED(pa_time))
03898 {
03899     ParticleSettings *part = psys->part;
03900     float size; // time XXX
03901     
03902     if(part->childtype==PART_CHILD_FACES)
03903         size=part->size;
03904     else
03905         size=psys->particles[cpa->parent].size;
03906 
03907     size*=part->childsize;
03908 
03909     if(part->childrandsize != 0.0f)
03910         size *= 1.0f - part->childrandsize * PSYS_FRAND(cpa - psys->child + 26);
03911 
03912     return size;
03913 }
03914 static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex)
03915 {
03916     ParticleSystem *psys = ctx->sim.psys;
03917     int i = cpa - psys->child;
03918 
03919     get_cpa_texture(ctx->dm, psys, part, psys->particles + cpa->pa[0], i, cpa_num, cpa_fuv, orco, ptex, PAMAP_DENS|PAMAP_CHILD, psys->cfra);
03920 
03921 
03922     if(ptex->exist < PSYS_FRAND(i + 24))
03923         return;
03924 
03925     if(ctx->vg_length)
03926         ptex->length*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_length);
03927     if(ctx->vg_clump)
03928         ptex->clump*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_clump);
03929     if(ctx->vg_kink)
03930         ptex->kink*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_kink);
03931     if(ctx->vg_rough1)
03932         ptex->rough1*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough1);
03933     if(ctx->vg_rough2)
03934         ptex->rough2*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_rough2);
03935     if(ctx->vg_roughe)
03936         ptex->roughe*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_roughe);
03937     if(ctx->vg_effector)
03938         ptex->effector*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_effector);
03939 }
03940 static void do_child_modifiers(ParticleSimulationData *sim, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, float mat[4][4], ParticleKey *state, float t)
03941 {
03942     ParticleSettings *part = sim->psys->part;
03943     int i = cpa - sim->psys->child;
03944     int guided = 0;
03945 
03946     float kink_freq = part->kink_freq;
03947     float rough1 = part->rough1;
03948     float rough2 = part->rough2;
03949     float rough_end = part->rough_end;
03950 
03951     if(ptex) {
03952         kink_freq *= ptex->kink;
03953         rough1 *= ptex->rough1;
03954         rough2 *= ptex->rough2;
03955         rough_end *= ptex->roughe;
03956     }
03957 
03958     if(part->flag & PART_CHILD_EFFECT)
03959         /* state is safe to cast, since only co and vel are used */
03960         guided = do_guides(sim->psys->effectors, (ParticleKey*)state, cpa->parent, t);
03961 
03962     if(guided==0){
03963         float clump = do_clump(state, par, t, part->clumpfac, part->clumppow, ptex ? ptex->clump : 1.f);
03964 
03965         if(kink_freq != 0.f) {
03966             float kink_amp = part->kink_amp * (1.f - part->kink_amp_clump * clump);
03967 
03968             do_kink(state, par, par_rot, t, kink_freq, part->kink_shape,
03969                     kink_amp, part->kink_flat, part->kink, part->kink_axis,
03970                     sim->ob->obmat, sim->psys->part->childtype == PART_CHILD_FACES);
03971         }
03972     }
03973 
03974     if(rough1 > 0.f)
03975         do_rough(orco, mat, t, rough1, part->rough1_size, 0.0, state);
03976 
03977     if(rough2 > 0.f)
03978         do_rough(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, rough2, part->rough2_size, part->rough2_thres, state);
03979 
03980     if(rough_end > 0.f)
03981         do_rough_end(sim->psys->frand + ((i + 27) % (PSYS_FRAND_COUNT - 3)), mat, t, rough_end, part->rough_end_shape, state);
03982 }
03983 /* get's hair (or keyed) particles state at the "path time" specified in state->time */
03984 void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *state, int vel)
03985 {
03986     PARTICLE_PSMD;
03987     ParticleSystem *psys = sim->psys;
03988     ParticleSettings *part = sim->psys->part;
03989     Material *ma = give_current_material(sim->ob, part->omat);
03990     ParticleData *pa;
03991     ChildParticle *cpa;
03992     ParticleTexture ptex;
03993     ParticleKey *par=0, keys[4], tstate;
03994     ParticleThreadContext ctx; /* fake thread context for child modifiers */
03995     ParticleInterpolationData pind;
03996 
03997     float t;
03998     float co[3], orco[3];
03999     float hairmat[4][4];
04000     int totpart = psys->totpart;
04001     int totchild = psys->totchild;
04002     short between = 0, edit = 0;
04003 
04004     int keyed = part->phystype & PART_PHYS_KEYED && psys->flag & PSYS_KEYED;
04005     int cached = !keyed && part->type != PART_HAIR;
04006 
04007     float *cpa_fuv; int cpa_num; short cpa_from;
04008 
04009     /* initialize keys to zero */
04010     memset(keys, 0, 4*sizeof(ParticleKey));
04011 
04012     t=state->time;
04013     CLAMP(t, 0.0f, 1.0f);
04014 
04015     if(p<totpart){
04016         pa = psys->particles + p;
04017         pind.keyed = keyed;
04018         pind.cache = cached ? psys->pointcache : NULL;
04019         pind.epoint = NULL;
04020         pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
04021         /* pind.dm disabled in editmode means we dont get effectors taken into
04022          * account when subdividing for instance */
04023         pind.dm = psys_in_edit_mode(sim->scene, psys) ? NULL : psys->hair_out_dm;
04024         init_particle_interpolation(sim->ob, psys, pa, &pind);
04025         do_particle_interpolation(psys, p, pa, t, &pind, state);
04026 
04027         if(pind.dm) {
04028             mul_m4_v3(sim->ob->obmat, state->co);
04029             mul_mat3_m4_v3(sim->ob->obmat, state->vel);
04030         }
04031         else if(!keyed && !cached && !(psys->flag & PSYS_GLOBAL_HAIR)) {
04032             if((pa->flag & PARS_REKEY)==0) {
04033                 psys_mat_hair_to_global(sim->ob, sim->psmd->dm, part->from, pa, hairmat);
04034                 mul_m4_v3(hairmat, state->co);
04035                 mul_mat3_m4_v3(hairmat, state->vel);
04036 
04037                 if(sim->psys->effectors && (part->flag & PART_CHILD_GUIDE)==0) {
04038                     do_guides(sim->psys->effectors, state, p, state->time);
04039                     /* TODO: proper velocity handling */
04040                 }
04041 
04042                 if(psys->lattice && edit==0)
04043                     calc_latt_deform(psys->lattice, state->co,1.0f);
04044             }
04045         }
04046     }
04047     else if(totchild){
04048         //invert_m4_m4(imat,ob->obmat);
04049 
04050         cpa=psys->child+p-totpart;
04051 
04052         if(state->time < 0.0f)
04053             t = psys_get_child_time(psys, cpa, -state->time, NULL, NULL);
04054         
04055         if(totchild && part->childtype==PART_CHILD_FACES){
04056             /* part->parents could still be 0 so we can't test with totparent */
04057             between=1;
04058         }
04059         if(between){
04060             int w = 0;
04061             float foffset;
04062 
04063             /* get parent states */
04064             while(w<4 && cpa->pa[w]>=0){
04065                 keys[w].time = state->time;
04066                 psys_get_particle_on_path(sim, cpa->pa[w], keys+w, 1);
04067                 w++;
04068             }
04069 
04070             /* get the original coordinates (orco) for texture usage */
04071             cpa_num=cpa->num;
04072             
04073             foffset= cpa->foffset;
04074             cpa_fuv = cpa->fuv;
04075             cpa_from = PART_FROM_FACE;
04076 
04077             psys_particle_on_emitter(psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa->fuv,foffset,co,0,0,0,orco,0);
04078 
04079             /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */
04080             //copy_v3_v3(cpa_1st,co);
04081 
04082             //mul_m4_v3(ob->obmat,cpa_1st);
04083 
04084             pa = psys->particles + cpa->parent;
04085 
04086             if(part->type == PART_HAIR)
04087                 psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
04088             else
04089                 unit_m4(hairmat);
04090 
04091             pa=0;
04092         }
04093         else{
04094             /* get the parent state */
04095             keys->time = state->time;
04096             psys_get_particle_on_path(sim, cpa->parent, keys,1);
04097 
04098             /* get the original coordinates (orco) for texture usage */
04099             pa=psys->particles+cpa->parent;
04100 
04101             cpa_from=part->from;
04102             cpa_num=pa->num;
04103             cpa_fuv=pa->fuv;
04104 
04105             
04106 
04107             if(part->type == PART_HAIR) {
04108                 psys_particle_on_emitter(psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,0,0,0,orco,0);
04109                 psys_mat_hair_to_global(sim->ob, sim->psmd->dm, psys->part->from, pa, hairmat);
04110             }
04111             else {
04112                 copy_v3_v3(orco, cpa->fuv);
04113                 unit_m4(hairmat);
04114             }
04115         }
04116 
04117         /* correct child ipo timing */
04118 #if 0 // XXX old animation system
04119         if((part->flag&PART_ABS_TIME)==0 && part->ipo){
04120             calc_ipo(part->ipo, 100.0f*t);
04121             execute_ipo((ID *)part, part->ipo);
04122         }
04123 #endif // XXX old animation system
04124         
04125         /* get different child parameters from textures & vgroups */
04126         memset(&ctx, 0, sizeof(ParticleThreadContext));
04127         ctx.sim = *sim;
04128         ctx.dm = psmd->dm;
04129         ctx.ma = ma;
04130         /* TODO: assign vertex groups */
04131         get_child_modifier_parameters(part, &ctx, cpa, cpa_from, cpa_num, cpa_fuv, orco, &ptex);
04132 
04133         if(between){
04134             int w=0;
04135 
04136             state->co[0] = state->co[1] = state->co[2] = 0.0f;
04137             state->vel[0] = state->vel[1] = state->vel[2] = 0.0f;
04138 
04139             /* child position is the weighted sum of parent positions */
04140             while(w<4 && cpa->pa[w]>=0){
04141                 state->co[0] += cpa->w[w] * keys[w].co[0];
04142                 state->co[1] += cpa->w[w] * keys[w].co[1];
04143                 state->co[2] += cpa->w[w] * keys[w].co[2];
04144 
04145                 state->vel[0] += cpa->w[w] * keys[w].vel[0];
04146                 state->vel[1] += cpa->w[w] * keys[w].vel[1];
04147                 state->vel[2] += cpa->w[w] * keys[w].vel[2];
04148                 w++;
04149             }
04150             /* apply offset for correct positioning */
04151             //add_v3_v3(state->co, cpa_1st);
04152         }
04153         else{
04154             /* offset the child from the parent position */
04155             offset_child(cpa, keys, keys->rot, state, part->childflat, part->childrad);
04156         }
04157 
04158         par = keys;
04159 
04160         if(vel)
04161             copy_particle_key(&tstate, state, 1);
04162 
04163         /* apply different deformations to the child path */
04164         do_child_modifiers(sim, &ptex, par, par->rot, cpa, orco, hairmat, state, t);
04165 
04166         /* try to estimate correct velocity */
04167         if(vel){
04168             ParticleKey tstate;
04169             float length = len_v3(state->vel);
04170 
04171             if(t>=0.001f){
04172                 tstate.time=t-0.001f;
04173                 psys_get_particle_on_path(sim,p,&tstate,0);
04174                 sub_v3_v3v3(state->vel,state->co,tstate.co);
04175                 normalize_v3(state->vel);
04176             }
04177             else{
04178                 tstate.time=t+0.001f;
04179                 psys_get_particle_on_path(sim,p,&tstate,0);
04180                 sub_v3_v3v3(state->vel,tstate.co,state->co);
04181                 normalize_v3(state->vel);
04182             }
04183 
04184             mul_v3_fl(state->vel, length);
04185         }
04186     }
04187 }
04188 /* gets particle's state at a time, returns 1 if particle exists and can be seen and 0 if not */
04189 int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *state, int always)
04190 {
04191     ParticleSystem *psys = sim->psys;
04192     ParticleSettings *part = psys->part;
04193     ParticleData *pa = NULL;
04194     ChildParticle *cpa = NULL;
04195     float cfra;
04196     int totpart = psys->totpart;
04197     float timestep = psys_get_timestep(sim);
04198 
04199     /* negative time means "use current time" */
04200     cfra = state->time > 0 ? state->time : BKE_curframe(sim->scene);
04201 
04202     if(p>=totpart){
04203         if(!psys->totchild)
04204             return 0;
04205 
04206         if(part->childtype == PART_CHILD_FACES){
04207             if(!(psys->flag & PSYS_KEYED))
04208                 return 0;
04209 
04210             cpa = psys->child + p - totpart;
04211 
04212             state->time = psys_get_child_time(psys, cpa, cfra, NULL, NULL);
04213 
04214             if(!always)
04215                 if((state->time < 0.0f && !(part->flag & PART_UNBORN))
04216                     || (state->time > 1.0f && !(part->flag & PART_DIED)))
04217                     return 0;
04218 
04219             state->time= (cfra - (part->sta + (part->end - part->sta) * PSYS_FRAND(p + 23))) / (part->lifetime * PSYS_FRAND(p + 24));
04220 
04221             psys_get_particle_on_path(sim, p, state,1);
04222             return 1;
04223         }
04224         else {
04225             cpa = sim->psys->child + p - totpart;
04226             pa = sim->psys->particles + cpa->parent;
04227         }
04228     }
04229     else {
04230         pa = sim->psys->particles + p;
04231     }
04232 
04233     if(pa) {
04234         if(!always)
04235             if((cfra < pa->time && (part->flag & PART_UNBORN)==0)
04236                 || (cfra > pa->dietime && (part->flag & PART_DIED)==0))
04237                 return 0;
04238 
04239         cfra = MIN2(cfra, pa->dietime);
04240     }
04241 
04242     if(sim->psys->flag & PSYS_KEYED){
04243         state->time= -cfra;
04244         psys_get_particle_on_path(sim, p, state,1);
04245         return 1;
04246     }
04247     else{
04248         if(cpa){
04249             float mat[4][4];
04250             ParticleKey *key1;
04251             float t = (cfra - pa->time) / pa->lifetime;
04252 
04253             key1=&pa->state;
04254             offset_child(cpa, key1, key1->rot, state, part->childflat, part->childrad);
04255 
04256             CLAMP(t, 0.0f, 1.0f);
04257 
04258             unit_m4(mat);
04259             do_child_modifiers(sim, NULL, key1, key1->rot, cpa, cpa->fuv, mat, state, t);
04260 
04261             if(psys->lattice)
04262                 calc_latt_deform(sim->psys->lattice, state->co,1.0f);
04263         }
04264         else{
04265             if(pa->state.time==cfra || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED))
04266                 copy_particle_key(state, &pa->state, 1);
04267             else if(pa->prev_state.time==cfra)
04268                 copy_particle_key(state, &pa->prev_state, 1);
04269             else {
04270                 float dfra, frs_sec = sim->scene->r.frs_sec;
04271                 /* let's interpolate to try to be as accurate as possible */
04272                 if(pa->state.time + 2.f >= state->time && pa->prev_state.time - 2.f <= state->time) {
04273                     if(pa->prev_state.time >= pa->state.time || pa->prev_state.time < 0.f) {
04274                         /* prev_state is wrong so let's not use it, this can happen at frames 1, 0 or particle birth */
04275                         dfra = state->time - pa->state.time;
04276 
04277                         copy_particle_key(state, &pa->state, 1);
04278 
04279                         madd_v3_v3v3fl(state->co, state->co, state->vel, dfra/frs_sec);
04280                     }
04281                     else {
04282                         ParticleKey keys[4];
04283                         float keytime;
04284 
04285                         copy_particle_key(keys+1, &pa->prev_state, 1);
04286                         copy_particle_key(keys+2, &pa->state, 1);
04287 
04288                         dfra = keys[2].time - keys[1].time;
04289 
04290                         keytime = (state->time - keys[1].time) / dfra;
04291 
04292                         /* convert velocity to timestep size */
04293                         mul_v3_fl(keys[1].vel, dfra * timestep);
04294                         mul_v3_fl(keys[2].vel, dfra * timestep);
04295                         
04296                         psys_interpolate_particle(-1, keys, keytime, state, 1);
04297                         
04298                         /* convert back to real velocity */
04299                         mul_v3_fl(state->vel, 1.f / (dfra * timestep));
04300 
04301                         interp_v3_v3v3(state->ave, keys[1].ave, keys[2].ave, keytime);
04302                         interp_qt_qtqt(state->rot, keys[1].rot, keys[2].rot, keytime);
04303                     }
04304                 }
04305                 else if(pa->state.time + 1.f >= state->time && pa->state.time - 1.f <= state->time) {
04306                     /* linear interpolation using only pa->state */
04307 
04308                     dfra = state->time - pa->state.time;
04309 
04310                     copy_particle_key(state, &pa->state, 1);
04311 
04312                     madd_v3_v3v3fl(state->co, state->co, state->vel, dfra/frs_sec);
04313                 }
04314                 else {
04315                     /* extrapolating over big ranges is not accurate so let's just give something close to reasonable back */
04316                     copy_particle_key(state, &pa->state, 0);
04317                 }
04318             }
04319 
04320             if(sim->psys->lattice)
04321                 calc_latt_deform(sim->psys->lattice, state->co,1.0f);
04322         }
04323         
04324         return 1;
04325     }
04326 }
04327 
04328 void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part, ParticleSystemModifierData *psmd, ParticleData *pa, ChildParticle *cpa, float *uv, float *orco)
04329 {
04330     MFace *mface;
04331     MTFace *mtface;
04332     float loc[3];
04333     int num;
04334 
04335     uv[0] = uv[1] = 0.f;
04336 
04337     if(cpa) {
04338         if(part->childtype == PART_CHILD_FACES) {
04339             mtface= CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE);
04340             if(mtface) {
04341                 mface= psmd->dm->getFaceData(psmd->dm, cpa->num, CD_MFACE);
04342                 mtface += cpa->num;
04343                 psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv);
04344             }
04345         
04346             psys_particle_on_emitter(psmd,PART_FROM_FACE,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,0,0,0,orco,0);
04347             return;
04348         }
04349         else {
04350             pa = psys->particles + cpa->pa[0];
04351         }
04352     }
04353 
04354     if(part->from == PART_FROM_FACE) {
04355         mtface= CustomData_get_layer(&psmd->dm->faceData, CD_MTFACE);
04356         num= pa->num_dmcache;
04357 
04358         if(num == DMCACHE_NOTFOUND)
04359             num= pa->num;
04360 
04361         if (num >= psmd->dm->getNumFaces(psmd->dm)) {
04362             /* happens when simplify is enabled
04363                 * gives invalid coords but would crash otherwise */
04364             num= DMCACHE_NOTFOUND;
04365         }
04366 
04367         if(mtface && num != DMCACHE_NOTFOUND) {
04368             mface= psmd->dm->getFaceData(psmd->dm, num, CD_MFACE);
04369             mtface += num;
04370             psys_interpolate_uvs(mtface, mface->v4, pa->fuv, uv);
04371         }
04372     }
04373 
04374     psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,0,0,0,orco,0);
04375 }
04376 
04377 void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[][4], float *scale)
04378 {
04379     Object *ob = sim->ob;
04380     ParticleSystem *psys = sim->psys;
04381     ParticleSystemModifierData *psmd = sim->psmd;
04382     float loc[3], nor[3], vec[3], side[3], len;
04383     float xvec[3] = {-1.0, 0.0, 0.0}, nmat[3][3];
04384 
04385     sub_v3_v3v3(vec, (cache+cache->steps)->co, cache->co);
04386     len= normalize_v3(vec);
04387 
04388     if(pa == NULL && psys->part->childflat != PART_CHILD_FACES)
04389         pa = psys->particles + cpa->pa[0];
04390 
04391     if(pa)
04392         psys_particle_on_emitter(psmd,sim->psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc,nor,0,0,0,0);
04393     else
04394         psys_particle_on_emitter(psmd,PART_FROM_FACE,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,loc,nor,0,0,0,0);
04395 
04396     if(psys->part->rotmode == PART_ROT_VEL) {
04397         copy_m3_m4(nmat, ob->imat);
04398         transpose_m3(nmat);
04399         mul_m3_v3(nmat, nor);
04400         normalize_v3(nor);
04401 
04402         /* make sure that we get a proper side vector */
04403         if(fabs(dot_v3v3(nor,vec))>0.999999) {
04404             if(fabs(dot_v3v3(nor,xvec))>0.999999) {
04405                 nor[0] = 0.0f;
04406                 nor[1] = 1.0f;
04407                 nor[2] = 0.0f;
04408             }
04409             else {
04410                 nor[0] = 1.0f;
04411                 nor[1] = 0.0f;
04412                 nor[2] = 0.0f;
04413             }
04414         }
04415         cross_v3_v3v3(side, nor, vec);
04416         normalize_v3(side);
04417 
04418         /* rotate side vector around vec */
04419         if(psys->part->phasefac != 0) {
04420             float q_phase[4];
04421             float phasefac = psys->part->phasefac;
04422             if(psys->part->randphasefac != 0.0f)
04423                 phasefac += psys->part->randphasefac * PSYS_FRAND((pa-psys->particles) + 20);
04424             axis_angle_to_quat( q_phase, vec, phasefac*(float)M_PI);
04425 
04426             mul_qt_v3(q_phase, side);
04427         }
04428 
04429         cross_v3_v3v3(nor, vec, side);
04430 
04431         unit_m4(mat);
04432         copy_v3_v3(mat[0], vec);
04433         copy_v3_v3(mat[1], side);
04434         copy_v3_v3(mat[2], nor);
04435     }
04436     else {
04437         quat_to_mat4(mat, pa->state.rot);
04438     }
04439 
04440     *scale= len;
04441 }
04442 
04443 void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3])
04444 {
04445     float onevec[3] = {0.0f,0.0f,0.0f}, tvec[3], tvec2[3];
04446 
04447     xvec[0] = 1.0f; xvec[1] = 0.0f; xvec[2] = 0.0f;
04448     yvec[0] = 0.0f; yvec[1] = 1.0f; yvec[2] = 0.0f;
04449 
04450     /* can happen with bad pointcache or physics calculation
04451      * since this becomes geometry, nan's and inf's crash raytrace code.
04452      * better not allow this. */
04453     if( !finite(bb->vec[0]) || !finite(bb->vec[1]) || !finite(bb->vec[2]) ||
04454         !finite(bb->vel[0]) || !finite(bb->vel[1]) || !finite(bb->vel[2]) )
04455     {
04456         zero_v3(bb->vec);
04457         zero_v3(bb->vel);
04458 
04459         zero_v3(xvec);
04460         zero_v3(yvec);
04461         zero_v3(zvec);
04462         zero_v3(center);
04463 
04464         return;
04465     }
04466 
04467     if(bb->align < PART_BB_VIEW)
04468         onevec[bb->align]=1.0f;
04469 
04470     if(bb->lock && (bb->align == PART_BB_VIEW)) {
04471         normalize_v3_v3(xvec, bb->ob->obmat[0]);
04472         normalize_v3_v3(yvec, bb->ob->obmat[1]);
04473         normalize_v3_v3(zvec, bb->ob->obmat[2]);
04474     }
04475     else if(bb->align == PART_BB_VEL) {
04476         float temp[3];
04477 
04478         normalize_v3_v3(temp, bb->vel);
04479 
04480         sub_v3_v3v3(zvec, bb->ob->obmat[3], bb->vec);
04481 
04482         if(bb->lock) {
04483             float fac = -dot_v3v3(zvec, temp);
04484 
04485             madd_v3_v3fl(zvec, temp, fac);
04486         }
04487         normalize_v3(zvec);
04488 
04489         cross_v3_v3v3(xvec,temp,zvec);
04490         normalize_v3(xvec);
04491 
04492         cross_v3_v3v3(yvec,zvec,xvec);
04493     }
04494     else {
04495         sub_v3_v3v3(zvec, bb->ob->obmat[3], bb->vec);
04496         if(bb->lock)
04497             zvec[bb->align] = 0.0f;
04498         normalize_v3(zvec);
04499 
04500         if(bb->align < PART_BB_VIEW)
04501             cross_v3_v3v3(xvec, onevec, zvec);
04502         else
04503             cross_v3_v3v3(xvec, bb->ob->obmat[1], zvec);
04504         normalize_v3(xvec);
04505 
04506         cross_v3_v3v3(yvec,zvec,xvec);
04507     }
04508 
04509     copy_v3_v3(tvec, xvec);
04510     copy_v3_v3(tvec2, yvec);
04511 
04512     mul_v3_fl(xvec, cos(bb->tilt * (float)M_PI));
04513     mul_v3_fl(tvec2, sin(bb->tilt * (float)M_PI));
04514     add_v3_v3(xvec, tvec2);
04515 
04516     mul_v3_fl(yvec, cos(bb->tilt * (float)M_PI));
04517     mul_v3_fl(tvec, -sin(bb->tilt * (float)M_PI));
04518     add_v3_v3(yvec, tvec);
04519 
04520     mul_v3_fl(xvec, bb->size[0]);
04521     mul_v3_fl(yvec, bb->size[1]);
04522 
04523     madd_v3_v3v3fl(center, bb->vec, xvec, bb->offset[0]);
04524     madd_v3_v3fl(center, yvec, bb->offset[1]);
04525 }
04526 
04527 
04528 void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
04529 {
04530     ParticleSimulationData sim= {0};
04531     sim.scene= scene;
04532     sim.ob= ob;
04533     sim.psys= psys;
04534     sim.psmd= psys_get_modifier(ob, psys);
04535 
04536     psys->lattice = psys_get_lattice(&sim);
04537 
04538     if(psys->lattice) {
04539         ParticleData *pa = psys->particles;
04540         HairKey *hkey;
04541         int p, h;
04542         float hairmat[4][4], imat[4][4];
04543 
04544         for(p=0; p<psys->totpart; p++, pa++) {
04545             psys_mat_hair_to_global(sim.ob, sim.psmd->dm, psys->part->from, pa, hairmat);
04546             invert_m4_m4(imat, hairmat);
04547 
04548             hkey = pa->hair;
04549             for(h=0; h<pa->totkey; h++, hkey++) {
04550                 mul_m4_v3(hairmat, hkey->co);
04551                 calc_latt_deform(psys->lattice, hkey->co, 1.0f);
04552                 mul_m4_v3(imat, hkey->co);
04553             }
04554         }
04555         
04556         end_latt_deform(psys->lattice);
04557         psys->lattice= NULL;
04558 
04559         /* protect the applied shape */
04560         psys->flag |= PSYS_EDITED;
04561     }
04562 }