Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2007-11-27 01:09:57 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2007-11-27 01:09:57 +0300
commit7da56f4a9ba0bdd0cdcd40b8ca6e69d776d26abe (patch)
tree663c13aae5606937571ac1e7a4c77ca2866e75dd /source/blender/blenkernel/intern/modifier.c
parent121dab1bcd9467bd8e11d0a82e83a1621758fd8e (diff)
parent770291b9ea1ec03d98b6bae4fd2a2d3f0091be41 (diff)
Particles
========= Merge of the famous particle patch by Janne Karhu, a full rewrite of the Blender particle system. This includes: - Emitter, Hair and Reactor particle types. - Newtonian, Keyed and Boids physics. - Various particle visualisation and rendering types. - Vertex group and texture control for various properties. - Interpolated child particles from parents. - Hair editing with combing, growing, cutting, .. . - Explode modifier. - Harmonic, Magnetic fields, and multiple falloff types. .. and lots of other things, some more info is here: http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite http://wiki.blender.org/index.php/BlenderDev/Particles_Rewrite_Doc The new particle system cannot be backwards compatible. Old particle systems are being converted to the new system, but will require tweaking to get them looking the same as before. Point Cache =========== The new system to replace manual baking, based on automatic caching on disk. This is currently used by softbodies and the particle system. See the Cache API section on: http://wiki.blender.org/index.php/BlenderDev/PhysicsSprint Documentation ============= These new features still need good docs for the release logs, help for this is appreciated.
Diffstat (limited to 'source/blender/blenkernel/intern/modifier.c')
-rw-r--r--source/blender/blenkernel/intern/modifier.c1281
1 files changed, 1277 insertions, 4 deletions
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 3a6611a2be7..9336dde0151 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -41,10 +41,11 @@
#include "math.h"
#include "float.h"
-#include "BLI_blenlib.h"
-#include "BLI_rand.h"
#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_kdtree.h"
#include "BLI_linklist.h"
+#include "BLI_rand.h"
#include "BLI_edgehash.h"
#include "BLI_ghash.h"
#include "BLI_memarena.h"
@@ -59,6 +60,7 @@
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
#include "DNA_object_force.h"
+#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
#include "DNA_curve_types.h"
@@ -72,20 +74,24 @@
#include "BKE_main.h"
#include "BKE_anim.h"
#include "BKE_bad_level_calls.h"
+#include "BKE_curve.h"
#include "BKE_customdata.h"
#include "BKE_global.h"
-#include "BKE_utildefines.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_DerivedMesh.h"
#include "BKE_booleanops.h"
#include "BKE_displist.h"
#include "BKE_modifier.h"
#include "BKE_lattice.h"
+#include "BKE_library.h"
#include "BKE_subsurf.h"
#include "BKE_object.h"
#include "BKE_mesh.h"
#include "BKE_softbody.h"
#include "BKE_material.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+#include "BKE_utildefines.h"
#include "depsgraph_private.h"
#include "LOD_DependKludge.h"
@@ -4685,7 +4691,7 @@ static void armatureModifier_deformVerts(
armature_deform_verts(amd->object, ob, derivedData, vertexCos, NULL,
numVerts, amd->deformflag,
- amd->prevCos, amd->defgrp_name);
+ (float(*)[3])amd->prevCos, amd->defgrp_name);
/* free cache */
if(amd->prevCos) {
MEM_freeN(amd->prevCos);
@@ -4998,6 +5004,1220 @@ static DerivedMesh *booleanModifier_applyModifier(
return derivedData;
}
+/* Particles */
+static void particleSystemModifier_initData(ModifierData *md)
+{
+ ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
+ psmd->psys= 0;
+ psmd->dm=0;
+
+}
+static void particleSystemModifier_freeData(ModifierData *md)
+{
+ ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
+
+ if(psmd->dm){
+ psmd->dm->needsFree = 1;
+ psmd->dm->release(psmd->dm);
+ psmd->dm=0;
+ }
+
+ psmd->psys->flag &= ~PSYS_ENABLED;
+ psmd->psys->flag |= PSYS_DELETE;
+}
+static void particleSystemModifier_copyData(ModifierData *md, ModifierData *target)
+{
+ ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
+ ParticleSystemModifierData *tpsmd= (ParticleSystemModifierData*) target;
+
+ tpsmd->dm = 0;
+ //tpsmd->facepa = 0;
+ tpsmd->flag = psmd->flag;
+ /* need to keep this to recognise a bit later in copy_object */
+ tpsmd->psys = psmd->psys;
+}
+
+CustomDataMask particleSystemModifier_requiredDataMask(ModifierData *md)
+{
+ ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
+ CustomDataMask dataMask = (1 << CD_MTFACE) + (1 << CD_MEDGE);
+ int i;
+
+ /* ask for vertexgroups if we need them */
+ for(i=0; i<PSYS_TOT_VG; i++){
+ if(psmd->psys->vgroup[i]){
+ dataMask |= (1 << CD_MDEFORMVERT);
+ break;
+ }
+ }
+
+ /* particles only need this if they are after a non deform modifier, and
+ * the modifier stack will only create them in that case. */
+ dataMask |= CD_MASK_ORIGSPACE;
+
+ return dataMask;
+}
+static int is_last_displist(Object *ob)
+{
+ Curve *cu = ob->data;
+ static int curvecount=0, totcurve=0;
+
+ if(curvecount==0){
+ DispList *dl;
+
+ totcurve=0;
+ for(dl=cu->disp.first; dl; dl=dl->next){
+ totcurve++;
+ }
+ }
+
+ curvecount++;
+
+ if(curvecount==totcurve){
+ curvecount=0;
+ return 1;
+ }
+
+ return 0;
+}
+/* saves the current emitter state for a particle system and calculates particles */
+static void particleSystemModifier_deformVerts(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm = derivedData;
+ ParticleSystemModifierData *psmd= (ParticleSystemModifierData*) md;
+ ParticleSystem * psys=0;
+ int totvert=0,totedge=0,totface=0,needsFree=0;
+
+ if(ob->particlesystem.first)
+ psys=psmd->psys;
+ else
+ return;
+
+ if((psys->flag&PSYS_ENABLED)==0)
+ return;
+
+ if(dm==0){
+ if(ob->type==OB_MESH){
+ dm = CDDM_from_mesh((Mesh*)(ob->data), ob);
+
+ CDDM_apply_vert_coords(dm, vertexCos);
+ //CDDM_calc_normals(dm);
+
+ needsFree=1;
+ }
+ else if(ELEM3(ob->type,OB_FONT,OB_CURVE,OB_SURF)){
+ Object *tmpobj;
+ Curve *tmpcu;
+
+ if(is_last_displist(ob)){
+ /* copies object and modifiers (but not the data) */
+ tmpobj= copy_object( ob );
+ tmpcu = (Curve *)tmpobj->data;
+ tmpcu->id.us--;
+
+ /* copies the data */
+ tmpobj->data = copy_curve( (Curve *) ob->data );
+
+ makeDispListCurveTypes( tmpobj, 1 );
+ nurbs_to_mesh( tmpobj );
+
+ dm = CDDM_from_mesh((Mesh*)(tmpobj->data), tmpobj);
+ //CDDM_calc_normals(dm);
+
+ free_libblock_us( &G.main->object, tmpobj );
+
+ needsFree=1;
+ }
+ else return;
+ }
+ else return;
+ }
+
+ /* clear old dm */
+ if(psmd->dm){
+ totvert=psmd->dm->getNumVerts(psmd->dm);
+ totedge=psmd->dm->getNumEdges(psmd->dm);
+ totface=psmd->dm->getNumFaces(psmd->dm);
+ psmd->dm->needsFree = 1;
+ psmd->dm->release(psmd->dm);
+ }
+
+ /* make new dm */
+ psmd->dm=CDDM_copy(dm);
+ CDDM_calc_normals(psmd->dm);
+
+ if(needsFree){
+ dm->needsFree = 1;
+ dm->release(dm);
+ }
+
+ /* protect dm */
+ psmd->dm->needsFree = 0;
+
+ /* report change in mesh structure */
+ if(psmd->dm->getNumVerts(psmd->dm)!=totvert ||
+ psmd->dm->getNumEdges(psmd->dm)!=totedge ||
+ psmd->dm->getNumFaces(psmd->dm)!=totface){
+ /* in file read dm hasn't really changed but just wasn't saved in file */
+ if(psmd->flag & eParticleSystemFlag_Loaded)
+ psmd->flag &= ~eParticleSystemFlag_Loaded;
+ else{
+ /* TODO PARTICLE - Added this so changing subsurf under hair updates it
+ should it be done elsewhere? - Campbell */
+ psys->recalc |= PSYS_RECALC_HAIR;
+ psys->recalc |= PSYS_DISTR;
+ psmd->flag |= eParticleSystemFlag_DM_changed;
+ }
+ }
+
+ if(psys){
+ particle_system_update(ob,psys);
+ psmd->flag |= eParticleSystemFlag_psys_updated;
+ psmd->flag &= ~eParticleSystemFlag_DM_changed;
+ }
+}
+
+static void particleSystemModifier_deformVertsEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts)
+{
+ DerivedMesh *dm = derivedData;
+
+ if(!derivedData) dm = CDDM_from_editmesh(editData, ob->data);
+
+ particleSystemModifier_deformVerts(md, ob, dm, vertexCos, numVerts);
+
+ if(!derivedData) dm->release(dm);
+}
+
+/* Particle Instance */
+static void particleInstanceModifier_initData(ModifierData *md)
+{
+ ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
+
+ pimd->flag = eParticleInstanceFlag_Parents|eParticleInstanceFlag_Unborn|
+ eParticleInstanceFlag_Alive|eParticleInstanceFlag_Dead;
+ pimd->psys = 1;
+
+}
+static void particleInstanceModifier_copyData(ModifierData *md, ModifierData *target)
+{
+ ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
+ ParticleInstanceModifierData *tpimd= (ParticleInstanceModifierData*) target;
+
+ tpimd->ob = pimd->ob;
+ tpimd->psys = pimd->psys;
+ tpimd->flag = pimd->flag;
+}
+
+static int particleInstanceModifier_dependsOnTime(ModifierData *md)
+{
+ return 0;
+}
+static void particleInstanceModifier_updateDepgraph(ModifierData *md, DagForest *forest,
+ Object *ob, DagNode *obNode)
+{
+ ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
+
+ if (pimd->ob) {
+ DagNode *curNode = dag_get_node(forest, pimd->ob);
+
+ dag_add_relation(forest, curNode, obNode,
+ DAG_RL_DATA_DATA | DAG_RL_OB_DATA);
+ }
+}
+
+static void particleInstanceModifier_foreachObjectLink(ModifierData *md, Object *ob,
+ ObjectWalkFunc walk, void *userData)
+{
+ ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData*) md;
+
+ walk(userData, ob, &pimd->ob);
+}
+
+static DerivedMesh * particleInstanceModifier_applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *dm = derivedData, *result;
+ ParticleInstanceModifierData *pimd= (ParticleInstanceModifierData*) md;
+ ParticleSystem * psys=0;
+ ParticleData *pa=0, *pars=0;
+ MFace *mface, *orig_mface;
+ MVert *mvert, *orig_mvert;
+ int i,totvert, totpart=0, totface, maxvert, maxface, first_particle=0;
+ short track=ob->trackflag%3, trackneg;
+ float max_co=0.0, min_co=0.0, temp_co[3];
+
+ trackneg=((ob->trackflag>2)?1:0);
+
+ if(pimd->ob==ob){
+ pimd->ob=0;
+ return derivedData;
+ }
+
+ if(pimd->ob){
+ psys = BLI_findlink(&pimd->ob->particlesystem,pimd->psys-1);
+ if(psys==0 || psys->totpart==0)
+ return derivedData;
+ }
+ else return derivedData;
+
+ if(pimd->flag & eParticleInstanceFlag_Parents)
+ totpart+=psys->totpart;
+ if(pimd->flag & eParticleInstanceFlag_Children){
+ if(totpart==0)
+ first_particle=psys->totpart;
+ totpart+=psys->totchild;
+ }
+
+ if(totpart==0)
+ return derivedData;
+
+ pars=psys->particles;
+
+ totvert=dm->getNumVerts(dm);
+ totface=dm->getNumFaces(dm);
+
+ maxvert=totvert*totpart;
+ maxface=totface*totpart;
+
+ psys->lattice=psys_get_lattice(ob, psys);
+
+ if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED)){
+ float co[3];
+ for(i=0; i< totvert; i++){
+ dm->getVertCo(dm,i,co);
+ if(i==0){
+ min_co=max_co=co[track];
+ }
+ else{
+ if(co[track]<min_co)
+ min_co=co[track];
+
+ if(co[track]>max_co)
+ max_co=co[track];
+ }
+ }
+ }
+
+ result = CDDM_from_template(dm, maxvert,dm->getNumEdges(dm)*totpart,maxface);
+
+ mvert=result->getVertArray(result);
+ orig_mvert=dm->getVertArray(dm);
+
+ for(i=0; i<maxvert; i++){
+ MVert *inMV;
+ MVert *mv = mvert + i;
+ ParticleKey state;
+
+ inMV = orig_mvert + i%totvert;
+ DM_copy_vert_data(dm, result, i%totvert, i, 1);
+ *mv = *inMV;
+
+ /*change orientation based on object trackflag*/
+ VECCOPY(temp_co,mv->co);
+ mv->co[0]=temp_co[track];
+ mv->co[1]=temp_co[(track+1)%3];
+ mv->co[2]=temp_co[(track+2)%3];
+
+ if(psys->flag & (PSYS_HAIR_DONE|PSYS_KEYED) && pimd->flag & eParticleInstanceFlag_Path){
+ state.time=(mv->co[0]-min_co)/(max_co-min_co);
+ if(trackneg)
+ state.time=1.0f-state.time;
+ psys_get_particle_on_path(pimd->ob,psys,first_particle + i/totvert,&state,1);
+ }
+ else{
+ state.time=-1.0;
+ psys_get_particle_state(pimd->ob,psys,i/totvert,&state,1);
+ }
+
+ /*displace vertice to path location*/
+ if(pimd->flag & eParticleInstanceFlag_Path)
+ mv->co[0]=0.0;
+
+ QuatMulVecf(state.rot,mv->co);
+ VECADD(mv->co,mv->co,state.co);
+ }
+
+ mface=result->getFaceArray(result);
+ orig_mface=dm->getFaceArray(dm);
+
+ for(i=0; i<maxface; i++){
+ MFace *inMF;
+ MFace *mf = mface + i;
+
+ if(pimd->flag & eParticleInstanceFlag_Parents){
+ if(i/totface>=psys->totpart){
+ if(psys->part->childtype==PART_CHILD_PARTICLES)
+ pa=psys->particles+(psys->child+i/totface-psys->totpart)->parent;
+ else
+ pa=0;
+ }
+ else
+ pa=pars+i/totface;
+ }
+ else{
+ if(psys->part->childtype==PART_CHILD_PARTICLES)
+ pa=psys->particles+(psys->child+i/totface)->parent;
+ else
+ pa=0;
+ }
+
+ if(pa){
+ if(pa->alive==PARS_UNBORN && (pimd->flag&eParticleInstanceFlag_Unborn)==0) continue;
+ if(pa->alive==PARS_ALIVE && (pimd->flag&eParticleInstanceFlag_Alive)==0) continue;
+ if(pa->alive==PARS_DEAD && (pimd->flag&eParticleInstanceFlag_Dead)==0) continue;
+ }
+
+ inMF = orig_mface + i%totface;
+ DM_copy_face_data(dm, result, i%totface, i, 1);
+ *mf = *inMF;
+
+ mf->v1+=(i/totface)*totvert;
+ mf->v2+=(i/totface)*totvert;
+ mf->v3+=(i/totface)*totvert;
+ if(mf->v4)
+ mf->v4+=(i/totface)*totvert;
+ }
+
+ CDDM_calc_edges(result);
+ CDDM_calc_normals(result);
+
+ if(psys->lattice){
+ end_latt_deform();
+ psys->lattice=0;
+ }
+
+ return result;
+}
+static DerivedMesh *particleInstanceModifier_applyModifierEM(
+ ModifierData *md, Object *ob, EditMesh *editData,
+ DerivedMesh *derivedData)
+{
+ return particleInstanceModifier_applyModifier(md, ob, derivedData, 0, 1);
+}
+
+/* Explode */
+static void explodeModifier_initData(ModifierData *md)
+{
+ ExplodeModifierData *emd= (ExplodeModifierData*) md;
+
+ emd->facepa=0;
+ emd->flag |= eExplodeFlag_Unborn+eExplodeFlag_Alive+eExplodeFlag_Dead;
+}
+static void explodeModifier_freeData(ModifierData *md)
+{
+ ExplodeModifierData *emd= (ExplodeModifierData*) md;
+
+ if(emd->facepa) MEM_freeN(emd->facepa);
+}
+static void explodeModifier_copyData(ModifierData *md, ModifierData *target)
+{
+ ExplodeModifierData *emd= (ExplodeModifierData*) md;
+ ExplodeModifierData *temd= (ExplodeModifierData*) target;
+
+ temd->facepa = 0;
+ temd->flag = emd->flag;
+}
+static int explodeModifier_dependsOnTime(ModifierData *md)
+{
+ return 1;
+}
+CustomDataMask explodeModifier_requiredDataMask(ModifierData *md)
+{
+ ExplodeModifierData *emd= (ExplodeModifierData*) md;
+ CustomDataMask dataMask = 0;
+
+ if(emd->vgroup)
+ dataMask |= (1 << CD_MDEFORMVERT);
+
+ return dataMask;
+}
+
+/* this should really be put somewhere permanently */
+static float vert_weight(MDeformVert *dvert, int group)
+{
+ MDeformWeight *dw;
+ int i;
+
+ if(dvert) {
+ dw= dvert->dw;
+ for(i= dvert->totweight; i>0; i--, dw++) {
+ if(dw->def_nr == group) return dw->weight;
+ if(i==1) break; /*otherwise dw will point to somewhere it shouldn't*/
+ }
+ }
+ return 0.0;
+}
+
+static void explodeModifier_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){
+ for(i=0; i<totvert; i++){
+ val = BLI_frand();
+ val = (1.0f-emd->protect)*val + emd->protect*0.5f;
+ if(val < vert_weight(dvert+i,emd->vgroup-1))
+ 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(ob,dm,psys->part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,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++){
+ VecAddf(center,mvert[fa->v1].co,mvert[fa->v2].co);
+ VecAddf(center,center,mvert[fa->v3].co);
+ if(fa->v4){
+ VecAddf(center,center,mvert[fa->v4].co);
+ VecMulf(center,0.25);
+ }
+ else
+ VecMulf(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 DerivedMesh * explodeModifier_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;
+ int totvert=dm->getNumVerts(dm);
+ int totface=dm->getNumFaces(dm);
+
+ int *edgesplit = MEM_callocN(sizeof(int)*totvert*totvert,"explode_edgesplit");
+ int *facesplit = MEM_callocN(sizeof(int)*totface,"explode_edgesplit");
+ 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;
+
+ /* 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){
+ edgesplit[mf->v1*totvert+mf->v2]=edgesplit[mf->v2*totvert+mf->v1]=1;
+ (*fs)++;
+ }
+
+ if(v2!=v3){
+ edgesplit[mf->v2*totvert+mf->v3]=edgesplit[mf->v3*totvert+mf->v2]=1;
+ (*fs)++;
+ }
+
+ if(v3!=v4){
+ edgesplit[mf->v3*totvert+mf->v4]=edgesplit[mf->v4*totvert+mf->v3]=1;
+ (*fs)++;
+ }
+
+ if(v1!=v4){
+ edgesplit[mf->v1*totvert+mf->v4]=edgesplit[mf->v4*totvert+mf->v1]=1;
+ (*fs)++;
+ }
+
+ if(*fs==2){
+ if((v1==v2 && v3==v4) || (v1==v4 && v2==v3))
+ *fs=1;
+ else if(v1!=v2){
+ if(v1!=v4)
+ edgesplit[mf->v2*totvert+mf->v3]=edgesplit[mf->v3*totvert+mf->v2]=1;
+ else
+ edgesplit[mf->v3*totvert+mf->v4]=edgesplit[mf->v4*totvert+mf->v3]=1;
+ }
+ else{
+ if(v1!=v4)
+ edgesplit[mf->v1*totvert+mf->v2]=edgesplit[mf->v2*totvert+mf->v1]=1;
+ else
+ edgesplit[mf->v1*totvert+mf->v4]=edgesplit[mf->v4*totvert+mf->v1]=1;
+ }
+ }
+ }
+ }
+
+ /* count splits & reindex */
+ totesplit=totvert;
+ for(j=0; j<totvert; j++){
+ for(i=j+1; i<totvert; i++){
+ if(edgesplit[j*totvert+i])
+ edgesplit[j*totvert+i]=edgesplit[i*totvert+j]=totesplit++;
+ }
+ }
+ /* 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;
+ for(j=0; j<totvert; j++){
+ for(i=j+1; i<totvert; i++){
+ if(edgesplit[j*totvert+i]){
+ mv=CDDM_get_vert(splitdm,j);
+ dupve=CDDM_get_vert(splitdm,edgesplit[j*totvert+i]);
+
+ DM_copy_vert_data(splitdm,splitdm,j,edgesplit[j*totvert+i],1);
+
+ *dupve=*mv;
+
+ mv=CDDM_get_vert(splitdm,i);
+
+ VECADD(dupve->co,dupve->co,mv->co);
+ VecMulf(dupve->co,0.5);
+ }
+ }
+ }
+
+ /* 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[mf->v1*totvert+mf->v4];
+ df1->v2=edgesplit[mf->v2*totvert+mf->v3];
+ mf->v3=df1->v2;
+ mf->v4=df1->v1;
+ }
+ else{
+ df1->v1=edgesplit[mf->v1*totvert+mf->v2];
+ df1->v4=edgesplit[mf->v3*totvert+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[mf->v1*totvert+mf->v4];
+ df1->v2=edgesplit[mf->v1*totvert+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[mf->v1*totvert+mf->v2];
+ df1->v3=edgesplit[mf->v2*totvert+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[mf->v3*totvert+mf->v4];
+ df1->v4=edgesplit[mf->v1*totvert+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[mf->v2*totvert+mf->v3];
+ df1->v4=edgesplit[mf->v3*totvert+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[mf->v1*totvert+mf->v4];
+ df3->v1=df1->v2=edgesplit[mf->v2*totvert+mf->v3];
+ df3->v3=df2->v2=df1->v3=edgesplit[mf->v3*totvert+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[mf->v1*totvert+mf->v4];
+ df2->v2=df1->v2=edgesplit[mf->v1*totvert+mf->v2];
+ df3->v2=df1->v3=edgesplit[mf->v3*totvert+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[mf->v1*totvert+mf->v2];
+ df2->v3=df1->v2=edgesplit[mf->v2*totvert+mf->v3];
+ df3->v3=df1->v3=edgesplit[mf->v1*totvert+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[mf->v1*totvert+mf->v2];
+ df3->v3=df2->v1=df1->v2=edgesplit[mf->v2*totvert+mf->v3];
+ df2->v3=df1->v3=edgesplit[mf->v3*totvert+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);
+ VecMulf(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[mf->v1*totvert+mf->v2];
+ df3->v2=df1->v3=edgesplit[mf->v2*totvert+mf->v3];
+
+ df2->v1=edgesplit[mf->v1*totvert+mf->v4];
+ df3->v4=df2->v3=edgesplit[mf->v3*totvert+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[mf->v1*totvert+mf->v2];
+ df3->v1=df1->v2=df1->v3=edgesplit[mf->v2*totvert+mf->v3];
+ df2->v1=df1->v4=edgesplit[mf->v1*totvert+mf->v4];
+
+ df3->v3=df2->v3=edgesplit[mf->v3*totvert+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[mf->v1*totvert+mf->v2];
+ df2->v4=df1->v3=edgesplit[mf->v3*totvert+mf->v4];
+ df1->v4=edgesplit[mf->v1*totvert+mf->v4];
+
+ df3->v3=df2->v2=edgesplit[mf->v2*totvert+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));
+ }
+ }
+
+ MEM_freeN(edgesplit);
+ MEM_freeN(facesplit);
+ MEM_freeN(vertpa);
+
+ return splitdm;
+
+}
+static DerivedMesh * explodeModifier_explodeMesh(ExplodeModifierData *emd,
+ ParticleSystemModifierData *psmd, Object *ob,
+ DerivedMesh *to_explode)
+{
+ DerivedMesh *explode, *dm=to_explode;
+ MFace *mf=0;
+ MVert *dupvert=0;
+ ParticleSettings *part=psmd->psys->part;
+ ParticleData *pa, *pars=psmd->psys->particles;
+ ParticleKey state;
+ float *vertco=0, imat[4][4];
+ float loc0[3], nor[3];
+ float timestep, cfra;
+ int *facepa=emd->facepa, *vertpa=0;
+ int totdup=0,totvert=0,totface=0,totpart=0;
+ int i, j, v, mindex=0;
+
+ totface= dm->getNumFaces(dm);
+ totvert= dm->getNumVerts(dm);
+ totpart= psmd->psys->totpart;
+
+ timestep= psys_get_timestep(part);
+
+ if(part->flag & PART_GLOB_TIME)
+ cfra=bsystem_time(0,(float)G.scene->r.cfra,0.0);
+ else
+ cfra=bsystem_time(ob,(float)G.scene->r.cfra,0.0);
+
+ /* table for vertice <-> particle relations (row totpart+1 is for yet unexploded verts) */
+ vertpa = MEM_callocN(sizeof(int)*(totpart+1)*totvert, "explode_vertpatab");
+ for(i=0; i<(totpart+1)*totvert; i++)
+ vertpa[i] = -1;
+
+ for (i=0; i<totface; i++) {
+ if(facepa[i]==totpart || cfra <= (pars+facepa[i])->time)
+ mindex = totpart*totvert;
+ else
+ mindex = facepa[i]*totvert;
+
+ mf=CDDM_get_face(dm,i);
+
+ /*set face vertices to exist in particle group*/
+ vertpa[mindex+mf->v1] = 1;
+ vertpa[mindex+mf->v2] = 1;
+ vertpa[mindex+mf->v3] = 1;
+ if(mf->v4)
+ vertpa[mindex+mf->v4] = 1;
+ }
+
+ /*make new vertice indexes & count total vertices after duplication*/
+ for(i=0; i<(totpart+1)*totvert; i++){
+ if(vertpa[i] != -1)
+ vertpa[i] = totdup++;
+ }
+
+ /*the final duplicated vertices*/
+ explode= CDDM_from_template(dm, totdup, 0,totface);
+ dupvert= CDDM_get_verts(explode);
+
+ /* getting back to object space */
+ Mat4Invert(imat,ob->obmat);
+
+ psmd->psys->lattice = psys_get_lattice(ob, psmd->psys);
+
+ /*duplicate & displace vertices*/
+ for(i=0, pa=pars; i<=totpart; i++, pa++){
+ if(i!=totpart){
+ psys_particle_on_emitter(ob, psmd,part->from,pa->num,-1,pa->fuv,pa->foffset,loc0,nor,0,0);
+ Mat4MulVecfl(ob->obmat,loc0);
+
+ state.time=cfra;
+ psys_get_particle_state(ob,psmd->psys,i,&state,1);
+ }
+
+ for(j=0; j<totvert; j++){
+ v=vertpa[i*totvert+j];
+ if(v != -1) {
+ MVert source;
+ MVert *dest;
+
+ 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){
+ vertco=CDDM_get_vert(explode,v)->co;
+
+ Mat4MulVecfl(ob->obmat,vertco);
+
+ VECSUB(vertco,vertco,loc0);
+
+ /* apply rotation, size & location */
+ QuatMulVecf(state.rot,vertco);
+ VecMulf(vertco,pa->size);
+ VECADD(vertco,vertco,state.co);
+
+ Mat4MulVecfl(imat,vertco);
+ }
+ }
+ }
+ }
+
+ /*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 = totpart*totvert;
+ else
+ mindex = facepa[i]*totvert;
+
+ source.v1 = vertpa[mindex+source.v1];
+ source.v2 = vertpa[mindex+source.v2];
+ source.v3 = vertpa[mindex+source.v3];
+ if(source.v4)
+ source.v4 = vertpa[mindex+source.v4];
+
+ DM_copy_face_data(dm,explode,i,i,1);
+
+ *mf = source;
+
+ test_index_face(mf, &explode->faceData, i, (mf->v4 ? 4 : 3));
+ }
+
+
+ /* cleanup */
+ if(vertpa) MEM_freeN(vertpa);
+
+ /* finalization */
+ CDDM_calc_edges(explode);
+ CDDM_calc_normals(explode);
+
+ if(psmd->psys->lattice){
+ end_latt_deform();
+ psmd->psys->lattice=0;
+ }
+
+ return explode;
+}
+
+static ParticleSystemModifierData * explodeModifier_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 * explodeModifier_applyModifier(
+ ModifierData *md, Object *ob, DerivedMesh *derivedData,
+ int useRenderParams, int isFinalCalc)
+{
+ DerivedMesh *dm = derivedData;
+ ExplodeModifierData *emd= (ExplodeModifierData*) md;
+ ParticleSystemModifierData *psmd=explodeModifier_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;
+
+ /* 1. find faces to be exploded if needed */
+ if(emd->facepa==0 || psmd->flag&eParticleSystemFlag_Pars || emd->flag&eExplodeFlag_CalcFaces){
+ if(psmd->flag & eParticleSystemFlag_Pars)
+ psmd->flag &= ~eParticleSystemFlag_Pars;
+
+ if(emd->flag & eExplodeFlag_CalcFaces)
+ emd->flag &= ~eExplodeFlag_CalcFaces;
+
+ explodeModifier_createFacepa(emd,psmd,ob,derivedData);
+ }
+
+ /* 2. create new mesh */
+ if(emd->flag & eExplodeFlag_EdgeSplit){
+ int *facepa = emd->facepa;
+ DerivedMesh *splitdm=explodeModifier_splitEdges(emd,dm);
+ DerivedMesh *explode=explodeModifier_explodeMesh(emd,psmd,ob,splitdm);
+
+ MEM_freeN(emd->facepa);
+ emd->facepa=facepa;
+ splitdm->release(splitdm);
+ return explode;
+ }
+ else
+ return explodeModifier_explodeMesh(emd,psmd,ob,derivedData);
+ }
+ return derivedData;
+}
/* MeshDeform */
static void meshdeformModifier_initData(ModifierData *md)
@@ -5535,6 +6755,42 @@ ModifierTypeInfo *modifierType_getInfo(ModifierType type)
mti->deformVerts = meshdeformModifier_deformVerts;
mti->deformVertsEM = meshdeformModifier_deformVertsEM;
+ mti = INIT_TYPE(ParticleSystem);
+ mti->type = eModifierTypeType_OnlyDeform;
+ mti->flags = eModifierTypeFlag_AcceptsMesh
+ |eModifierTypeFlag_SupportsEditmode
+ |eModifierTypeFlag_EnableInEditmode;
+ mti->initData = particleSystemModifier_initData;
+ mti->freeData = particleSystemModifier_freeData;
+ mti->copyData = particleSystemModifier_copyData;
+ mti->deformVerts = particleSystemModifier_deformVerts;
+ mti->deformVertsEM = particleSystemModifier_deformVertsEM;
+ mti->requiredDataMask = particleSystemModifier_requiredDataMask;
+
+ mti = INIT_TYPE(ParticleInstance);
+ mti->type = eModifierTypeType_Constructive;
+ mti->flags = eModifierTypeFlag_AcceptsMesh
+ | eModifierTypeFlag_SupportsMapping
+ | eModifierTypeFlag_SupportsEditmode
+ | eModifierTypeFlag_EnableInEditmode;
+ mti->initData = particleInstanceModifier_initData;
+ mti->copyData = particleInstanceModifier_copyData;
+ mti->dependsOnTime = particleInstanceModifier_dependsOnTime;
+ mti->foreachObjectLink = particleInstanceModifier_foreachObjectLink;
+ mti->applyModifier = particleInstanceModifier_applyModifier;
+ mti->applyModifierEM = particleInstanceModifier_applyModifierEM;
+ mti->updateDepgraph = particleInstanceModifier_updateDepgraph;
+
+ mti = INIT_TYPE(Explode);
+ mti->type = eModifierTypeType_Nonconstructive;
+ mti->flags = eModifierTypeFlag_AcceptsMesh;
+ mti->initData = explodeModifier_initData;
+ mti->freeData = explodeModifier_freeData;
+ mti->copyData = explodeModifier_copyData;
+ mti->dependsOnTime = explodeModifier_dependsOnTime;
+ mti->requiredDataMask = explodeModifier_requiredDataMask;
+ mti->applyModifier = explodeModifier_applyModifier;
+
typeArrInit = 0;
#undef INIT_TYPE
}
@@ -5727,6 +6983,13 @@ int modifiers_isSoftbodyEnabled(Object *ob)
return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
}
+int modifiers_isParticleEnabled(Object *ob)
+{
+ ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleSystem);
+
+ return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render));
+}
+
LinkNode *modifiers_calcDataMasks(ModifierData *md, CustomDataMask dataMask)
{
LinkNode *dataMasks = NULL;
@@ -5910,3 +7173,13 @@ int modifiers_isDeformed(Object *ob)
return 0;
}
+int modifiers_indexInObject(Object *ob, ModifierData *md_seek)
+{
+ int i= 0;
+ ModifierData *md;
+
+ for (md=ob->modifiers.first; (md && md_seek!=md); md=md->next, i++);
+ if (!md) return -1; /* modifier isnt in the object */
+ return i;
+}
+