diff options
author | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2010-04-18 06:03:19 +0400 |
---|---|---|
committer | Tamito Kajiyama <rd6t-kjym@asahi-net.or.jp> | 2010-04-18 06:03:19 +0400 |
commit | dfe2f8dc03267e041102837e92f547fb04881510 (patch) | |
tree | d9582c4667ce5b9e39e2adce40832aa4f44b4fe7 /source/blender/modifiers/intern/MOD_explode.c | |
parent | d7e08f2d33207fdf76b1b597ef0de9dec26e3987 (diff) | |
parent | 00e46ef739cf2bfddb8805af056aa59fd3b3c71c (diff) |
Merged changes in the trunk up to revision 28247.
Diffstat (limited to 'source/blender/modifiers/intern/MOD_explode.c')
-rw-r--r-- | source/blender/modifiers/intern/MOD_explode.c | 902 |
1 files changed, 902 insertions, 0 deletions
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c new file mode 100644 index 00000000000..12f46d01e01 --- /dev/null +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -0,0 +1,902 @@ +/* +* $Id$ +* +* ***** BEGIN GPL LICENSE BLOCK ***** +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software Foundation, +* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +* +* The Original Code is Copyright (C) 2005 by the Blender Foundation. +* All rights reserved. +* +* Contributor(s): Daniel Dunbar +* Ton Roosendaal, +* Ben Batt, +* Brecht Van Lommel, +* Campbell Barton +* +* ***** END GPL LICENSE BLOCK ***** +* +*/ + +#include "DNA_meshdata_types.h" +#include "DNA_scene_types.h" + +#include "BLI_kdtree.h" +#include "BLI_rand.h" +#include "BLI_math.h" +#include "BLI_edgehash.h" + +#include "BKE_cdderivedmesh.h" +#include "BKE_lattice.h" +#include "BKE_mesh.h" +#include "BKE_modifier.h" +#include "BKE_object.h" +#include "BKE_particle.h" +#include "BKE_utildefines.h" +#include "BKE_deform.h" + +#include "MEM_guardedalloc.h" + + +static void initData(ModifierData *md) +{ + ExplodeModifierData *emd= (ExplodeModifierData*) md; + + emd->facepa=0; + emd->flag |= eExplodeFlag_Unborn+eExplodeFlag_Alive+eExplodeFlag_Dead; +} +static void freeData(ModifierData *md) +{ + ExplodeModifierData *emd= (ExplodeModifierData*) md; + + if(emd->facepa) MEM_freeN(emd->facepa); +} +static void copyData(ModifierData *md, ModifierData *target) +{ + ExplodeModifierData *emd= (ExplodeModifierData*) md; + ExplodeModifierData *temd= (ExplodeModifierData*) target; + + temd->facepa = 0; + temd->flag = emd->flag; + temd->protect = emd->protect; + temd->vgroup = emd->vgroup; +} +static int dependsOnTime(ModifierData *md) +{ + return 1; +} +static CustomDataMask requiredDataMask(Object *ob, ModifierData *md) +{ + ExplodeModifierData *emd= (ExplodeModifierData*) md; + CustomDataMask dataMask = 0; + + if(emd->vgroup) + dataMask |= (1 << CD_MDEFORMVERT); + + return dataMask; +} + +static void createFacepa(ExplodeModifierData *emd, + ParticleSystemModifierData *psmd, + Object *ob, DerivedMesh *dm) +{ + ParticleSystem *psys=psmd->psys; + MFace *fa=0, *mface=0; + MVert *mvert = 0; + ParticleData *pa; + KDTree *tree; + float center[3], co[3]; + int *facepa=0,*vertpa=0,totvert=0,totface=0,totpart=0; + int i,p,v1,v2,v3,v4=0; + + mvert = dm->getVertArray(dm); + mface = dm->getFaceArray(dm); + totface= dm->getNumFaces(dm); + totvert= dm->getNumVerts(dm); + totpart= psmd->psys->totpart; + + BLI_srandom(psys->seed); + + if(emd->facepa) + MEM_freeN(emd->facepa); + + facepa = emd->facepa = MEM_callocN(sizeof(int)*totface, "explode_facepa"); + + vertpa = MEM_callocN(sizeof(int)*totvert, "explode_vertpa"); + + /* initialize all faces & verts to no particle */ + for(i=0; i<totface; i++) + facepa[i]=totpart; + + for (i=0; i<totvert; i++) + vertpa[i]=totpart; + + /* set protected verts */ + if(emd->vgroup){ + MDeformVert *dvert = dm->getVertDataArray(dm, CD_MDEFORMVERT); + float val; + if(dvert){ + int defgrp_index= emd->vgroup-1; + for(i=0; i<totvert; i++, dvert++){ + val = BLI_frand(); + val = (1.0f-emd->protect)*val + emd->protect*0.5f; + if(val < defvert_find_weight(dvert, defgrp_index)) + vertpa[i] = -1; + } + } + } + + /* make tree of emitter locations */ + tree=BLI_kdtree_new(totpart); + for(p=0,pa=psys->particles; p<totpart; p++,pa++){ + psys_particle_on_dm(psmd->dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,0,0,0,0,0); + BLI_kdtree_insert(tree, p, co, NULL); + } + BLI_kdtree_balance(tree); + + /* set face-particle-indexes to nearest particle to face center */ + for(i=0,fa=mface; i<totface; i++,fa++){ + add_v3_v3v3(center,mvert[fa->v1].co,mvert[fa->v2].co); + add_v3_v3v3(center,center,mvert[fa->v3].co); + if(fa->v4){ + add_v3_v3v3(center,center,mvert[fa->v4].co); + mul_v3_fl(center,0.25); + } + else + mul_v3_fl(center,0.3333f); + + p= BLI_kdtree_find_nearest(tree,center,NULL,NULL); + + v1=vertpa[fa->v1]; + v2=vertpa[fa->v2]; + v3=vertpa[fa->v3]; + if(fa->v4) + v4=vertpa[fa->v4]; + + if(v1>=0 && v2>=0 && v3>=0 && (fa->v4==0 || v4>=0)) + facepa[i]=p; + + if(v1>=0) vertpa[fa->v1]=p; + if(v2>=0) vertpa[fa->v2]=p; + if(v3>=0) vertpa[fa->v3]=p; + if(fa->v4 && v4>=0) vertpa[fa->v4]=p; + } + + if(vertpa) MEM_freeN(vertpa); + BLI_kdtree_free(tree); +} + +static int edgesplit_get(EdgeHash *edgehash, int v1, int v2) +{ + return GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, v1, v2)); +} + +static DerivedMesh * splitEdges(ExplodeModifierData *emd, DerivedMesh *dm){ + DerivedMesh *splitdm; + MFace *mf=0,*df1=0,*df2=0,*df3=0; + MFace *mface=CDDM_get_faces(dm); + MVert *dupve, *mv; + EdgeHash *edgehash; + EdgeHashIterator *ehi; + int totvert=dm->getNumVerts(dm); + int totface=dm->getNumFaces(dm); + + int *facesplit = MEM_callocN(sizeof(int)*totface,"explode_facesplit"); + int *vertpa = MEM_callocN(sizeof(int)*totvert,"explode_vertpa2"); + int *facepa = emd->facepa; + int *fs, totesplit=0,totfsplit=0,totin=0,curdupvert=0,curdupface=0,curdupin=0; + int i,j,v1,v2,v3,v4,esplit; + + edgehash= BLI_edgehash_new(); + + /* recreate vertpa from facepa calculation */ + for (i=0,mf=mface; i<totface; i++,mf++) { + vertpa[mf->v1]=facepa[i]; + vertpa[mf->v2]=facepa[i]; + vertpa[mf->v3]=facepa[i]; + if(mf->v4) + vertpa[mf->v4]=facepa[i]; + } + + /* mark edges for splitting and how to split faces */ + for (i=0,mf=mface,fs=facesplit; i<totface; i++,mf++,fs++) { + if(mf->v4){ + v1=vertpa[mf->v1]; + v2=vertpa[mf->v2]; + v3=vertpa[mf->v3]; + v4=vertpa[mf->v4]; + + if(v1!=v2){ + BLI_edgehash_insert(edgehash, mf->v1, mf->v2, NULL); + (*fs)++; + } + + if(v2!=v3){ + BLI_edgehash_insert(edgehash, mf->v2, mf->v3, NULL); + (*fs)++; + } + + if(v3!=v4){ + BLI_edgehash_insert(edgehash, mf->v3, mf->v4, NULL); + (*fs)++; + } + + if(v1!=v4){ + BLI_edgehash_insert(edgehash, mf->v1, mf->v4, NULL); + (*fs)++; + } + + if(*fs==2){ + if((v1==v2 && v3==v4) || (v1==v4 && v2==v3)) + *fs=1; + else if(v1!=v2){ + if(v1!=v4) + BLI_edgehash_insert(edgehash, mf->v2, mf->v3, NULL); + else + BLI_edgehash_insert(edgehash, mf->v3, mf->v4, NULL); + } + else{ + if(v1!=v4) + BLI_edgehash_insert(edgehash, mf->v1, mf->v2, NULL); + else + BLI_edgehash_insert(edgehash, mf->v1, mf->v4, NULL); + } + } + } + } + + /* count splits & reindex */ + ehi= BLI_edgehashIterator_new(edgehash); + totesplit=totvert; + for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { + BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totesplit)); + totesplit++; + } + BLI_edgehashIterator_free(ehi); + + /* count new faces due to splitting */ + for(i=0,fs=facesplit; i<totface; i++,fs++){ + if(*fs==1) + totfsplit+=1; + else if(*fs==2) + totfsplit+=2; + else if(*fs==3) + totfsplit+=3; + else if(*fs==4){ + totfsplit+=3; + + mf=dm->getFaceData(dm,i,CD_MFACE);//CDDM_get_face(dm,i); + + if(vertpa[mf->v1]!=vertpa[mf->v2] && vertpa[mf->v2]!=vertpa[mf->v3]) + totin++; + } + } + + splitdm= CDDM_from_template(dm, totesplit+totin, dm->getNumEdges(dm),totface+totfsplit); + + /* copy new faces & verts (is it really this painful with custom data??) */ + for(i=0; i<totvert; i++){ + MVert source; + MVert *dest; + dm->getVert(dm, i, &source); + dest = CDDM_get_vert(splitdm, i); + + DM_copy_vert_data(dm, splitdm, i, i, 1); + *dest = source; + } + for(i=0; i<totface; i++){ + MFace source; + MFace *dest; + dm->getFace(dm, i, &source); + dest = CDDM_get_face(splitdm, i); + + DM_copy_face_data(dm, splitdm, i, i, 1); + *dest = source; + } + + /* override original facepa (original pointer is saved in caller function) */ + facepa= MEM_callocN(sizeof(int)*(totface+totfsplit),"explode_facepa"); + memcpy(facepa,emd->facepa,totface*sizeof(int)); + emd->facepa=facepa; + + /* create new verts */ + curdupvert=totvert; + ehi= BLI_edgehashIterator_new(edgehash); + for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { + BLI_edgehashIterator_getKey(ehi, &i, &j); + esplit= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); + mv=CDDM_get_vert(splitdm,j); + dupve=CDDM_get_vert(splitdm,esplit); + + DM_copy_vert_data(splitdm,splitdm,j,esplit,1); + + *dupve=*mv; + + mv=CDDM_get_vert(splitdm,i); + + add_v3_v3(dupve->co, mv->co); + mul_v3_fl(dupve->co, 0.5f); + } + BLI_edgehashIterator_free(ehi); + + /* create new faces */ + curdupface=totface; + curdupin=totesplit; + for(i=0,fs=facesplit; i<totface; i++,fs++){ + if(*fs){ + mf=CDDM_get_face(splitdm,i); + + v1=vertpa[mf->v1]; + v2=vertpa[mf->v2]; + v3=vertpa[mf->v3]; + v4=vertpa[mf->v4]; + /* ouch! creating new faces & remapping them to new verts is no fun */ + if(*fs==1){ + df1=CDDM_get_face(splitdm,curdupface); + DM_copy_face_data(splitdm,splitdm,i,curdupface,1); + *df1=*mf; + curdupface++; + + if(v1==v2){ + df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4); + df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3); + mf->v3=df1->v2; + mf->v4=df1->v1; + } + else{ + df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2); + df1->v4=edgesplit_get(edgehash, mf->v3, mf->v4); + mf->v2=df1->v1; + mf->v3=df1->v4; + } + + facepa[i]=v1; + facepa[curdupface-1]=v3; + + test_index_face(df1, &splitdm->faceData, curdupface, (df1->v4 ? 4 : 3)); + } + if(*fs==2){ + df1=CDDM_get_face(splitdm,curdupface); + DM_copy_face_data(splitdm,splitdm,i,curdupface,1); + *df1=*mf; + curdupface++; + + df2=CDDM_get_face(splitdm,curdupface); + DM_copy_face_data(splitdm,splitdm,i,curdupface,1); + *df2=*mf; + curdupface++; + + if(v1!=v2){ + if(v1!=v4){ + df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4); + df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2); + df2->v1=df1->v3=mf->v2; + df2->v3=df1->v4=mf->v4; + df2->v2=mf->v3; + + mf->v2=df1->v2; + mf->v3=df1->v1; + + df2->v4=mf->v4=0; + + facepa[i]=v1; + } + else{ + df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2); + df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3); + df1->v4=mf->v3; + df2->v2=mf->v3; + df2->v3=mf->v4; + + mf->v1=df1->v2; + mf->v3=df1->v3; + + df2->v4=mf->v4=0; + + facepa[i]=v2; + } + facepa[curdupface-1]=facepa[curdupface-2]=v3; + } + else{ + if(v1!=v4){ + df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4); + df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4); + df1->v2=mf->v3; + + mf->v1=df1->v4; + mf->v2=df1->v3; + mf->v3=mf->v4; + + df2->v4=mf->v4=0; + + facepa[i]=v4; + } + else{ + df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3); + df1->v4=edgesplit_get(edgehash, mf->v3, mf->v4); + df1->v1=mf->v4; + df1->v2=mf->v2; + df2->v3=mf->v4; + + mf->v1=df1->v4; + mf->v2=df1->v3; + + df2->v4=mf->v4=0; + + facepa[i]=v3; + } + + facepa[curdupface-1]=facepa[curdupface-2]=v1; + } + + test_index_face(df1, &splitdm->faceData, curdupface-2, (df1->v4 ? 4 : 3)); + test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3)); + } + else if(*fs==3){ + df1=CDDM_get_face(splitdm,curdupface); + DM_copy_face_data(splitdm,splitdm,i,curdupface,1); + *df1=*mf; + curdupface++; + + df2=CDDM_get_face(splitdm,curdupface); + DM_copy_face_data(splitdm,splitdm,i,curdupface,1); + *df2=*mf; + curdupface++; + + df3=CDDM_get_face(splitdm,curdupface); + DM_copy_face_data(splitdm,splitdm,i,curdupface,1); + *df3=*mf; + curdupface++; + + if(v1==v2){ + df2->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4); + df3->v1=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3); + df3->v3=df2->v2=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4); + df3->v2=mf->v3; + df2->v3=mf->v4; + df1->v4=df2->v4=df3->v4=0; + + mf->v3=df1->v2; + mf->v4=df1->v1; + + facepa[i]=facepa[curdupface-3]=v1; + facepa[curdupface-1]=v3; + facepa[curdupface-2]=v4; + } + else if(v2==v3){ + df3->v1=df2->v3=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v4); + df2->v2=df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2); + df3->v2=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4); + + df3->v3=mf->v4; + df2->v1=mf->v1; + df1->v4=df2->v4=df3->v4=0; + + mf->v1=df1->v2; + mf->v4=df1->v3; + + facepa[i]=facepa[curdupface-3]=v2; + facepa[curdupface-1]=v4; + facepa[curdupface-2]=v1; + } + else if(v3==v4){ + df3->v2=df2->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2); + df2->v3=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3); + df3->v3=df1->v3=edgesplit_get(edgehash, mf->v1, mf->v4); + + df3->v1=mf->v1; + df2->v2=mf->v2; + df1->v4=df2->v4=df3->v4=0; + + mf->v1=df1->v3; + mf->v2=df1->v2; + + facepa[i]=facepa[curdupface-3]=v3; + facepa[curdupface-1]=v1; + facepa[curdupface-2]=v2; + } + else{ + df3->v1=df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2); + df3->v3=df2->v1=df1->v2=edgesplit_get(edgehash, mf->v2, mf->v3); + df2->v3=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4); + + df3->v2=mf->v2; + df2->v2=mf->v3; + df1->v4=df2->v4=df3->v4=0; + + mf->v2=df1->v1; + mf->v3=df1->v3; + + facepa[i]=facepa[curdupface-3]=v1; + facepa[curdupface-1]=v2; + facepa[curdupface-2]=v3; + } + + test_index_face(df1, &splitdm->faceData, curdupface-3, (df1->v4 ? 4 : 3)); + test_index_face(df1, &splitdm->faceData, curdupface-2, (df1->v4 ? 4 : 3)); + test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3)); + } + else if(*fs==4){ + if(v1!=v2 && v2!=v3){ + + /* set new vert to face center */ + mv=CDDM_get_vert(splitdm,mf->v1); + dupve=CDDM_get_vert(splitdm,curdupin); + DM_copy_vert_data(splitdm,splitdm,mf->v1,curdupin,1); + *dupve=*mv; + + mv=CDDM_get_vert(splitdm,mf->v2); + VECADD(dupve->co,dupve->co,mv->co); + mv=CDDM_get_vert(splitdm,mf->v3); + VECADD(dupve->co,dupve->co,mv->co); + mv=CDDM_get_vert(splitdm,mf->v4); + VECADD(dupve->co,dupve->co,mv->co); + mul_v3_fl(dupve->co,0.25); + + + df1=CDDM_get_face(splitdm,curdupface); + DM_copy_face_data(splitdm,splitdm,i,curdupface,1); + *df1=*mf; + curdupface++; + + df2=CDDM_get_face(splitdm,curdupface); + DM_copy_face_data(splitdm,splitdm,i,curdupface,1); + *df2=*mf; + curdupface++; + + df3=CDDM_get_face(splitdm,curdupface); + DM_copy_face_data(splitdm,splitdm,i,curdupface,1); + *df3=*mf; + curdupface++; + + df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2); + df3->v2=df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3); + + df2->v1=edgesplit_get(edgehash, mf->v1, mf->v4); + df3->v4=df2->v3=edgesplit_get(edgehash, mf->v3, mf->v4); + + df3->v1=df2->v2=df1->v4=curdupin; + + mf->v2=df1->v1; + mf->v3=curdupin; + mf->v4=df2->v1; + + curdupin++; + + facepa[i]=v1; + facepa[curdupface-3]=v2; + facepa[curdupface-2]=v3; + facepa[curdupface-1]=v4; + + test_index_face(df1, &splitdm->faceData, curdupface-3, (df1->v4 ? 4 : 3)); + + test_index_face(df1, &splitdm->faceData, curdupface-2, (df1->v4 ? 4 : 3)); + test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3)); + } + else{ + df1=CDDM_get_face(splitdm,curdupface); + DM_copy_face_data(splitdm,splitdm,i,curdupface,1); + *df1=*mf; + curdupface++; + + df2=CDDM_get_face(splitdm,curdupface); + DM_copy_face_data(splitdm,splitdm,i,curdupface,1); + *df2=*mf; + curdupface++; + + df3=CDDM_get_face(splitdm,curdupface); + DM_copy_face_data(splitdm,splitdm,i,curdupface,1); + *df3=*mf; + curdupface++; + + if(v2==v3){ + df1->v1=edgesplit_get(edgehash, mf->v1, mf->v2); + df3->v1=df1->v2=df1->v3=edgesplit_get(edgehash, mf->v2, mf->v3); + df2->v1=df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4); + + df3->v3=df2->v3=edgesplit_get(edgehash, mf->v3, mf->v4); + + df3->v2=mf->v3; + df3->v4=0; + + mf->v2=df1->v1; + mf->v3=df1->v4; + mf->v4=0; + + facepa[i]=v1; + facepa[curdupface-3]=facepa[curdupface-2]=v2; + facepa[curdupface-1]=v3; + } + else{ + df3->v1=df2->v1=df1->v2=edgesplit_get(edgehash, mf->v1, mf->v2); + df2->v4=df1->v3=edgesplit_get(edgehash, mf->v3, mf->v4); + df1->v4=edgesplit_get(edgehash, mf->v1, mf->v4); + + df3->v3=df2->v2=edgesplit_get(edgehash, mf->v2, mf->v3); + + df3->v4=0; + + mf->v1=df1->v4; + mf->v2=df1->v3; + mf->v3=mf->v4; + mf->v4=0; + + facepa[i]=v4; + facepa[curdupface-3]=facepa[curdupface-2]=v1; + facepa[curdupface-1]=v2; + } + + test_index_face(df1, &splitdm->faceData, curdupface-3, (df1->v4 ? 4 : 3)); + test_index_face(df1, &splitdm->faceData, curdupface-2, (df1->v4 ? 4 : 3)); + test_index_face(df1, &splitdm->faceData, curdupface-1, (df1->v4 ? 4 : 3)); + } + } + + test_index_face(df1, &splitdm->faceData, i, (df1->v4 ? 4 : 3)); + } + } + + BLI_edgehash_free(edgehash, NULL); + MEM_freeN(facesplit); + MEM_freeN(vertpa); + + return splitdm; + +} +static DerivedMesh * explodeMesh(ExplodeModifierData *emd, + ParticleSystemModifierData *psmd, Scene *scene, Object *ob, + DerivedMesh *to_explode) +{ + DerivedMesh *explode, *dm=to_explode; + MFace *mf=0, *mface; + ParticleSettings *part=psmd->psys->part; + ParticleSimulationData sim = {scene, ob, psmd->psys, psmd}; + ParticleData *pa=NULL, *pars=psmd->psys->particles; + ParticleKey state; + EdgeHash *vertpahash; + EdgeHashIterator *ehi; + float *vertco=0, imat[4][4]; + float loc0[3], nor[3]; + float timestep, cfra; + int *facepa=emd->facepa; + int totdup=0,totvert=0,totface=0,totpart=0; + int i, j, v, mindex=0; + + totface= dm->getNumFaces(dm); + totvert= dm->getNumVerts(dm); + mface= dm->getFaceArray(dm); + totpart= psmd->psys->totpart; + + timestep= psys_get_timestep(&sim); + + //if(part->flag & PART_GLOB_TIME) + cfra=bsystem_time(scene, 0,(float)scene->r.cfra,0.0); + //else + // cfra=bsystem_time(scene, ob,(float)scene->r.cfra,0.0); + + /* hash table for vertice <-> particle relations */ + vertpahash= BLI_edgehash_new(); + + for (i=0; i<totface; i++) { + /* do mindex + totvert to ensure the vertex index to be the first + * with BLI_edgehashIterator_getKey */ + if(facepa[i]==totpart || cfra <= (pars+facepa[i])->time) + mindex = totvert+totpart; + else + mindex = totvert+facepa[i]; + + mf= &mface[i]; + + /* set face vertices to exist in particle group */ + BLI_edgehash_insert(vertpahash, mf->v1, mindex, NULL); + BLI_edgehash_insert(vertpahash, mf->v2, mindex, NULL); + BLI_edgehash_insert(vertpahash, mf->v3, mindex, NULL); + if(mf->v4) + BLI_edgehash_insert(vertpahash, mf->v4, mindex, NULL); + } + + /* make new vertice indexes & count total vertices after duplication */ + ehi= BLI_edgehashIterator_new(vertpahash); + for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { + BLI_edgehashIterator_setValue(ehi, SET_INT_IN_POINTER(totdup)); + totdup++; + } + BLI_edgehashIterator_free(ehi); + + /* the final duplicated vertices */ + explode= CDDM_from_template(dm, totdup, 0,totface); + /*dupvert= CDDM_get_verts(explode);*/ + + /* getting back to object space */ + invert_m4_m4(imat,ob->obmat); + + psmd->psys->lattice = psys_get_lattice(&sim); + + /* duplicate & displace vertices */ + ehi= BLI_edgehashIterator_new(vertpahash); + for(; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) { + MVert source; + MVert *dest; + + /* get particle + vertex from hash */ + BLI_edgehashIterator_getKey(ehi, &j, &i); + i -= totvert; + v= GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi)); + + dm->getVert(dm, j, &source); + dest = CDDM_get_vert(explode,v); + + DM_copy_vert_data(dm,explode,j,v,1); + *dest = source; + + if(i!=totpart) { + /* get particle */ + pa= pars+i; + + /* get particle state */ + psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc0,nor,0,0,0,0); + mul_m4_v3(ob->obmat,loc0); + + state.time=cfra; + psys_get_particle_state(&sim, i, &state, 1); + + vertco=CDDM_get_vert(explode,v)->co; + + mul_m4_v3(ob->obmat,vertco); + + VECSUB(vertco,vertco,loc0); + + /* apply rotation, size & location */ + mul_qt_v3(state.rot,vertco); + if(emd->flag & eExplodeFlag_PaSize) + mul_v3_fl(vertco,pa->size); + VECADD(vertco,vertco,state.co); + + mul_m4_v3(imat,vertco); + } + } + BLI_edgehashIterator_free(ehi); + + /*map new vertices to faces*/ + for (i=0; i<totface; i++) { + MFace source; + int orig_v4; + + if(facepa[i]!=totpart) + { + pa=pars+facepa[i]; + + if(pa->alive==PARS_UNBORN && (emd->flag&eExplodeFlag_Unborn)==0) continue; + if(pa->alive==PARS_ALIVE && (emd->flag&eExplodeFlag_Alive)==0) continue; + if(pa->alive==PARS_DEAD && (emd->flag&eExplodeFlag_Dead)==0) continue; + } + + dm->getFace(dm,i,&source); + mf=CDDM_get_face(explode,i); + + orig_v4 = source.v4; + + if(facepa[i]!=totpart && cfra <= pa->time) + mindex = totvert+totpart; + else + mindex = totvert+facepa[i]; + + source.v1 = edgesplit_get(vertpahash, source.v1, mindex); + source.v2 = edgesplit_get(vertpahash, source.v2, mindex); + source.v3 = edgesplit_get(vertpahash, source.v3, mindex); + if(source.v4) + source.v4 = edgesplit_get(vertpahash, source.v4, mindex); + + DM_copy_face_data(dm,explode,i,i,1); + + *mf = source; + + test_index_face(mf, &explode->faceData, i, (orig_v4 ? 4 : 3)); + } + + /* cleanup */ + BLI_edgehash_free(vertpahash, NULL); + + /* finalization */ + CDDM_calc_edges(explode); + CDDM_calc_normals(explode); + + if(psmd->psys->lattice){ + end_latt_deform(psmd->psys->lattice); + psmd->psys->lattice= NULL; + } + + return explode; +} + +static ParticleSystemModifierData * findPrecedingParticlesystem(Object *ob, ModifierData *emd) +{ + ModifierData *md; + ParticleSystemModifierData *psmd=0; + + for (md=ob->modifiers.first; emd!=md; md=md->next){ + if(md->type==eModifierType_ParticleSystem) + psmd= (ParticleSystemModifierData*) md; + } + return psmd; +} +static DerivedMesh * applyModifier( + ModifierData *md, Object *ob, DerivedMesh *derivedData, + int useRenderParams, int isFinalCalc) +{ + DerivedMesh *dm = derivedData; + ExplodeModifierData *emd= (ExplodeModifierData*) md; + ParticleSystemModifierData *psmd=findPrecedingParticlesystem(ob,md); + + if(psmd){ + ParticleSystem * psys=psmd->psys; + + if(psys==0 || psys->totpart==0) return derivedData; + if(psys->part==0 || psys->particles==0) return derivedData; + if(psmd->dm==0) return derivedData; + + /* 1. find faces to be exploded if needed */ + if(emd->facepa==0 + || psmd->flag&eParticleSystemFlag_Pars + || emd->flag&eExplodeFlag_CalcFaces + || MEM_allocN_len(emd->facepa)/sizeof(int) != dm->getNumFaces(dm)){ + if(psmd->flag & eParticleSystemFlag_Pars) + psmd->flag &= ~eParticleSystemFlag_Pars; + + if(emd->flag & eExplodeFlag_CalcFaces) + emd->flag &= ~eExplodeFlag_CalcFaces; + + createFacepa(emd,psmd,ob,derivedData); + } + + /* 2. create new mesh */ + if(emd->flag & eExplodeFlag_EdgeSplit){ + int *facepa = emd->facepa; + DerivedMesh *splitdm=splitEdges(emd,dm); + DerivedMesh *explode=explodeMesh(emd, psmd, md->scene, ob, splitdm); + + MEM_freeN(emd->facepa); + emd->facepa=facepa; + splitdm->release(splitdm); + return explode; + } + else + return explodeMesh(emd, psmd, md->scene, ob, derivedData); + } + return derivedData; +} + + +ModifierTypeInfo modifierType_Explode = { + /* name */ "Explode", + /* structName */ "ExplodeModifierData", + /* structSize */ sizeof(ExplodeModifierData), + /* type */ eModifierTypeType_Nonconstructive, + /* flags */ eModifierTypeFlag_AcceptsMesh, + /* copyData */ copyData, + /* deformVerts */ 0, + /* deformVertsEM */ 0, + /* deformMatricesEM */ 0, + /* applyModifier */ applyModifier, + /* applyModifierEM */ 0, + /* initData */ initData, + /* requiredDataMask */ requiredDataMask, + /* freeData */ freeData, + /* isDisabled */ 0, + /* updateDepgraph */ 0, + /* dependsOnTime */ dependsOnTime, + /* foreachObjectLink */ 0, + /* foreachIDLink */ 0, +}; |