Blender  V2.59
MOD_particleinstance.c
Go to the documentation of this file.
00001 /*
00002 * $Id: MOD_particleinstance.c 35817 2011-03-27 13:49:53Z campbellbarton $
00003 *
00004 * ***** BEGIN GPL LICENSE BLOCK *****
00005 *
00006 * This program is free software; you can redistribute it and/or
00007 * modify it under the terms of the GNU General Public License
00008 * as published by the Free Software Foundation; either version 2
00009 * of the License, or (at your option) any later version.
00010 *
00011 * This program is distributed in the hope that it will be useful,
00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 * GNU General Public License for more details.
00015 *
00016 * You should have received a copy of the GNU General Public License
00017 * along with this program; if not, write to the Free Software  Foundation,
00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019 *
00020 * The Original Code is Copyright (C) 2005 by the Blender Foundation.
00021 * All rights reserved.
00022 *
00023 * Contributor(s): Daniel Dunbar
00024 *                 Ton Roosendaal,
00025 *                 Ben Batt,
00026 *                 Brecht Van Lommel,
00027 *                 Campbell Barton
00028 *
00029 * ***** END GPL LICENSE BLOCK *****
00030 *
00031 */
00032 
00038 #include "DNA_meshdata_types.h"
00039 
00040 #include "MEM_guardedalloc.h"
00041 
00042 #include "BLI_math.h"
00043 #include "BLI_listbase.h"
00044 #include "BLI_rand.h"
00045 #include "BLI_utildefines.h"
00046 
00047 #include "BKE_cdderivedmesh.h"
00048 #include "BKE_lattice.h"
00049 #include "BKE_modifier.h"
00050 #include "BKE_particle.h"
00051 #include "BKE_pointcache.h"
00052 
00053 #include "MOD_util.h"
00054 
00055 #include "depsgraph_private.h"
00056 
00057 
00058 static void initData(ModifierData *md)
00059 {
00060         ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
00061 
00062         pimd->flag = eParticleInstanceFlag_Parents|eParticleInstanceFlag_Unborn|
00063                         eParticleInstanceFlag_Alive|eParticleInstanceFlag_Dead;
00064         pimd->psys = 1;
00065         pimd->position = 1.0f;
00066         pimd->axis = 2;
00067 
00068 }
00069 static void copyData(ModifierData *md, ModifierData *target)
00070 {
00071         ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
00072         ParticleInstanceModifierData *tpimd= (ParticleInstanceModifierData*) target;
00073 
00074         tpimd->ob = pimd->ob;
00075         tpimd->psys = pimd->psys;
00076         tpimd->flag = pimd->flag;
00077         tpimd->axis = pimd->axis;
00078         tpimd->position = pimd->position;
00079         tpimd->random_position = pimd->random_position;
00080 }
00081 
00082 static int dependsOnTime(ModifierData *UNUSED(md))
00083 {
00084         return 0;
00085 }
00086 static void updateDepgraph(ModifierData *md, DagForest *forest,
00087                                                 struct Scene *UNUSED(scene),
00088                                                 Object *UNUSED(ob),
00089                                                 DagNode *obNode)
00090 {
00091         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
00092 
00093         if (pimd->ob) {
00094                 DagNode *curNode = dag_get_node(forest, pimd->ob);
00095 
00096                 dag_add_relation(forest, curNode, obNode,
00097                                  DAG_RL_DATA_DATA | DAG_RL_OB_DATA,
00098                                  "Particle Instance Modifier");
00099         }
00100 }
00101 
00102 static void foreachObjectLink(ModifierData *md, Object *ob,
00103                 ObjectWalkFunc walk, void *userData)
00104 {
00105         ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
00106 
00107         walk(userData, ob, &pimd->ob);
00108 }
00109 
00110 static DerivedMesh * applyModifier(ModifierData *md, Object *ob,
00111                                                 DerivedMesh *derivedData,
00112                                                 int UNUSED(useRenderParams),
00113                                                 int UNUSED(isFinalCalc))
00114 {
00115         DerivedMesh *dm = derivedData, *result;
00116         ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
00117         ParticleSimulationData sim;
00118         ParticleSystem *psys= NULL;
00119         ParticleData *pa= NULL, *pars= NULL;
00120         MFace *mface, *orig_mface;
00121         MVert *mvert, *orig_mvert;
00122         int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0;
00123         short track=ob->trackflag%3, trackneg, axis = pimd->axis;
00124         float max_co=0.0, min_co=0.0, temp_co[3], cross[3];
00125         float *size=NULL;
00126 
00127         trackneg=((ob->trackflag>2)?1:0);
00128 
00129         if(pimd->ob==ob){
00130                 pimd->ob= NULL;
00131                 return derivedData;
00132         }
00133 
00134         if(pimd->ob){
00135                 psys = BLI_findlink(&pimd->ob->particlesystem,pimd->psys-1);
00136                 if(psys==NULL || psys->totpart==0)
00137                         return derivedData;
00138         }
00139         else return derivedData;
00140 
00141         if(pimd->flag & eParticleInstanceFlag_Parents)
00142                 totpart+=psys->totpart;
00143         if(pimd->flag & eParticleInstanceFlag_Children){
00144                 if(totpart==0)
00145                         first_particle=psys->totpart;
00146                 totpart+=psys->totchild;
00147         }
00148 
00149         if(totpart==0)
00150                 return derivedData;
00151 
00152         sim.scene = md->scene;
00153         sim.ob = pimd->ob;
00154         sim.psys = psys;
00155         sim.psmd = psys_get_modifier(pimd->ob, psys);
00156 
00157         if(pimd->flag & eParticleInstanceFlag_UseSize) {
00158                 int p;
00159                 float *si;
00160                 si = size = MEM_callocN(totpart * sizeof(float), "particle size array");
00161 
00162                 if(pimd->flag & eParticleInstanceFlag_Parents) {
00163                         for(p=0, pa= psys->particles; p<psys->totpart; p++, pa++, si++)
00164                                 *si = pa->size;
00165                 }
00166 
00167                 if(pimd->flag & eParticleInstanceFlag_Children) {
00168                         ChildParticle *cpa = psys->child;
00169 
00170                         for(p=0; p<psys->totchild; p++, cpa++, si++) {
00171                                 *si = psys_get_child_size(psys, cpa, 0.0f, NULL);
00172                         }
00173                 }
00174         }
00175 
00176         pars=psys->particles;
00177 
00178         totvert=dm->getNumVerts(dm);
00179         totface=dm->getNumFaces(dm);
00180 
00181         maxvert=totvert*totpart;
00182         maxface=totface*totpart;
00183 
00184         psys->lattice=psys_get_lattice(&sim);
00185 
00186         if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED){
00187 
00188                 float min_r[3], max_r[3];
00189                 INIT_MINMAX(min_r, max_r);
00190                 dm->getMinMax(dm, min_r, max_r);
00191                 min_co=min_r[track];
00192                 max_co=max_r[track];
00193         }
00194 
00195         result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface);
00196 
00197         mvert=result->getVertArray(result);
00198         orig_mvert=dm->getVertArray(dm);
00199 
00200         for(i=0; i<maxvert; i++){
00201                 MVert *inMV;
00202                 MVert *mv = mvert + i;
00203                 ParticleKey state;
00204 
00205                 inMV = orig_mvert + i%totvert;
00206                 DM_copy_vert_data(dm, result, i%totvert, i, 1);
00207                 *mv = *inMV;
00208 
00209                 /*change orientation based on object trackflag*/
00210                 copy_v3_v3(temp_co, mv->co);
00211                 mv->co[axis]=temp_co[track];
00212                 mv->co[(axis+1)%3]=temp_co[(track+1)%3];
00213                 mv->co[(axis+2)%3]=temp_co[(track+2)%3];
00214 
00215                 if((psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) && pimd->flag & eParticleInstanceFlag_Path){
00216                         float ran = 0.0f;
00217                         if(pimd->random_position != 0.0f) {
00218                                 BLI_srandom(psys->seed + (i/totvert)%totpart);
00219                                 ran = pimd->random_position * BLI_frand();
00220                         }
00221 
00222                         if(pimd->flag & eParticleInstanceFlag_KeepShape) {
00223                                 state.time = pimd->position * (1.0f - ran);
00224                         }
00225                         else {
00226                                 state.time=(mv->co[axis]-min_co)/(max_co-min_co) * pimd->position * (1.0f - ran);
00227 
00228                                 if(trackneg)
00229                                         state.time=1.0f-state.time;
00230 
00231                                 mv->co[axis] = 0.0;
00232                         }
00233 
00234                         psys_get_particle_on_path(&sim, first_particle + i/totvert, &state,1);
00235 
00236                         normalize_v3(state.vel);
00237 
00238                         /* TODO: incremental rotations somehow */
00239                         if(state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
00240                                 state.rot[0] = 1;
00241                                 state.rot[1] = state.rot[2] = state.rot[3] = 0.0f;
00242                         }
00243                         else {
00244                                 float temp[3] = {0.0f,0.0f,0.0f};
00245                                 temp[axis] = 1.0f;
00246 
00247                                 cross_v3_v3v3(cross, temp, state.vel);
00248 
00249                                 /* state.vel[axis] is the only component surviving from a dot product with the axis */
00250                                 axis_angle_to_quat(state.rot,cross,saacos(state.vel[axis]));
00251                         }
00252 
00253                 }
00254                 else{
00255                         state.time=-1.0;
00256                         psys_get_particle_state(&sim, first_particle + i/totvert, &state,1);
00257                 }
00258 
00259                 mul_qt_v3(state.rot,mv->co);
00260                 if(pimd->flag & eParticleInstanceFlag_UseSize)
00261                         mul_v3_fl(mv->co, size[i/totvert]);
00262                 VECADD(mv->co,mv->co,state.co);
00263         }
00264 
00265         mface=result->getFaceArray(result);
00266         orig_mface=dm->getFaceArray(dm);
00267 
00268         for(i=0; i<maxface; i++){
00269                 MFace *inMF;
00270                 MFace *mf = mface + i;
00271 
00272                 if(pimd->flag & eParticleInstanceFlag_Parents){
00273                         if(i/totface>=psys->totpart){
00274                                 if(psys->part->childtype==PART_CHILD_PARTICLES)
00275                                         pa=psys->particles+(psys->child+i/totface-psys->totpart)->parent;
00276                                 else
00277                                         pa= NULL;
00278                         }
00279                         else
00280                                 pa=pars+i/totface;
00281                 }
00282                 else{
00283                         if(psys->part->childtype==PART_CHILD_PARTICLES)
00284                                 pa=psys->particles+(psys->child+i/totface)->parent;
00285                         else
00286                                 pa= NULL;
00287                 }
00288 
00289                 if(pa){
00290                         if(pa->alive==PARS_UNBORN && (pimd->flag&eParticleInstanceFlag_Unborn)==0) continue;
00291                         if(pa->alive==PARS_ALIVE && (pimd->flag&eParticleInstanceFlag_Alive)==0) continue;
00292                         if(pa->alive==PARS_DEAD && (pimd->flag&eParticleInstanceFlag_Dead)==0) continue;
00293                 }
00294 
00295                 inMF = orig_mface + i%totface;
00296                 DM_copy_face_data(dm, result, i%totface, i, 1);
00297                 *mf = *inMF;
00298 
00299                 mf->v1+=(i/totface)*totvert;
00300                 mf->v2+=(i/totface)*totvert;
00301                 mf->v3+=(i/totface)*totvert;
00302                 if(mf->v4)
00303                         mf->v4+=(i/totface)*totvert;
00304         }
00305 
00306         CDDM_calc_edges(result);
00307         CDDM_calc_normals(result);
00308 
00309         if(psys->lattice){
00310                 end_latt_deform(psys->lattice);
00311                 psys->lattice= NULL;
00312         }
00313 
00314         if(size)
00315                 MEM_freeN(size);
00316 
00317         return result;
00318 }
00319 static DerivedMesh *applyModifierEM(ModifierData *md, Object *ob,
00320                                                 struct EditMesh *UNUSED(editData),
00321                                                 DerivedMesh *derivedData)
00322 {
00323         return applyModifier(md, ob, derivedData, 0, 1);
00324 }
00325 
00326 
00327 ModifierTypeInfo modifierType_ParticleInstance = {
00328         /* name */              "ParticleInstance",
00329         /* structName */        "ParticleInstanceModifierData",
00330         /* structSize */        sizeof(ParticleInstanceModifierData),
00331         /* type */              eModifierTypeType_Constructive,
00332         /* flags */             eModifierTypeFlag_AcceptsMesh
00333                                                         | eModifierTypeFlag_SupportsMapping
00334                                                         | eModifierTypeFlag_SupportsEditmode
00335                                                         | eModifierTypeFlag_EnableInEditmode,
00336 
00337         /* copyData */          copyData,
00338         /* deformVerts */       NULL,
00339         /* deformMatrices */    NULL,
00340         /* deformVertsEM */     NULL,
00341         /* deformMatricesEM */  NULL,
00342         /* applyModifier */     applyModifier,
00343         /* applyModifierEM */   applyModifierEM,
00344         /* initData */          initData,
00345         /* requiredDataMask */  NULL,
00346         /* freeData */          NULL,
00347         /* isDisabled */        NULL,
00348         /* updateDepgraph */    updateDepgraph,
00349         /* dependsOnTime */     dependsOnTime,
00350         /* dependsOnNormals */  NULL,
00351         /* foreachObjectLink */ foreachObjectLink,
00352         /* foreachIDLink */     NULL,
00353 };