Blender V2.61 - r43446

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