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:
authorLukas Tönne <lukas.toenne@gmail.com>2016-12-28 19:30:58 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2016-12-28 19:30:58 +0300
commit6ecab6dd8e48d564a2b43e0e81e79d079e8b4c77 (patch)
tree618e2d24eb34a05a81f726dd52eb2b7468e9296d /source/blender/modifiers/intern
parent605263177b8eea24c1449e4dbf0138175ec3dddf (diff)
Revert particle system and point cache removal in blender2.8 branch.
This reverts commit 5aa19be91263a249ffae75573e3b32f24269d890 and b4a721af694817fa921b119df83d33ede7d7fed0. Due to postponement of particle system rewrite it was decided to put particle code back into the 2.8 branch for the time being.
Diffstat (limited to 'source/blender/modifiers/intern')
-rw-r--r--source/blender/modifiers/intern/MOD_build.c2
-rw-r--r--source/blender/modifiers/intern/MOD_cloth.c13
-rw-r--r--source/blender/modifiers/intern/MOD_collision.c2
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c943
-rw-r--r--source/blender/modifiers/intern/MOD_laplaciandeform.c3
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c470
-rw-r--r--source/blender/modifiers/intern/MOD_particlesystem.c241
-rw-r--r--source/blender/modifiers/intern/MOD_shapekey.c2
-rw-r--r--source/blender/modifiers/intern/MOD_smooth.c2
-rw-r--r--source/blender/modifiers/intern/MOD_softbody.c2
-rw-r--r--source/blender/modifiers/intern/MOD_solidify.c2
-rw-r--r--source/blender/modifiers/intern/MOD_util.c2
12 files changed, 1673 insertions, 11 deletions
diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c
index 8f3e1c24141..a364eef2974 100644
--- a/source/blender/modifiers/intern/MOD_build.c
+++ b/source/blender/modifiers/intern/MOD_build.c
@@ -41,10 +41,10 @@
#include "BLI_ghash.h"
#include "DNA_meshdata_types.h"
-#include "DNA_object_types.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_modifier.h"
+#include "BKE_particle.h"
#include "BKE_scene.h"
#ifdef _OPENMP
diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c
index 0b99aa55c8d..d15a6fcb1c8 100644
--- a/source/blender/modifiers/intern/MOD_cloth.c
+++ b/source/blender/modifiers/intern/MOD_cloth.c
@@ -37,7 +37,6 @@
#include "DNA_cloth_types.h"
#include "DNA_key_types.h"
#include "DNA_scene_types.h"
-#include "DNA_object_force.h"
#include "DNA_object_types.h"
#include "MEM_guardedalloc.h"
@@ -52,6 +51,7 @@
#include "BKE_key.h"
#include "BKE_library_query.h"
#include "BKE_modifier.h"
+#include "BKE_pointcache.h"
#include "depsgraph_private.h"
@@ -63,9 +63,10 @@ static void initData(ModifierData *md)
clmd->sim_parms = MEM_callocN(sizeof(ClothSimSettings), "cloth sim parms");
clmd->coll_parms = MEM_callocN(sizeof(ClothCollSettings), "cloth coll parms");
+ clmd->point_cache = BKE_ptcache_add(&clmd->ptcaches);
/* check for alloc failing */
- if (!clmd->sim_parms || !clmd->coll_parms)
+ if (!clmd->sim_parms || !clmd->coll_parms || !clmd->point_cache)
return;
cloth_init(clmd);
@@ -173,10 +174,15 @@ static void copyData(ModifierData *md, ModifierData *target)
if (tclmd->coll_parms)
MEM_freeN(tclmd->coll_parms);
+ BKE_ptcache_free_list(&tclmd->ptcaches);
+ tclmd->point_cache = NULL;
+
tclmd->sim_parms = MEM_dupallocN(clmd->sim_parms);
if (clmd->sim_parms->effector_weights)
tclmd->sim_parms->effector_weights = MEM_dupallocN(clmd->sim_parms->effector_weights);
tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms);
+ tclmd->point_cache = BKE_ptcache_add(&tclmd->ptcaches);
+ tclmd->point_cache->step = 1;
tclmd->clothObject = NULL;
tclmd->hairdata = NULL;
tclmd->solver_result = NULL;
@@ -205,6 +211,9 @@ static void freeData(ModifierData *md)
if (clmd->coll_parms)
MEM_freeN(clmd->coll_parms);
+ BKE_ptcache_free_list(&clmd->ptcaches);
+ clmd->point_cache = NULL;
+
if (clmd->hairdata)
MEM_freeN(clmd->hairdata);
diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c
index 8790d8083a6..e7ff0a90fbc 100644
--- a/source/blender/modifiers/intern/MOD_collision.c
+++ b/source/blender/modifiers/intern/MOD_collision.c
@@ -34,7 +34,6 @@
#include "DNA_object_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_object_force.h"
#include "MEM_guardedalloc.h"
@@ -46,6 +45,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_global.h"
#include "BKE_modifier.h"
+#include "BKE_pointcache.h"
#include "BKE_scene.h"
static void initData(ModifierData *md)
diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c
index 97f4423b798..38ffdaa709b 100644
--- a/source/blender/modifiers/intern/MOD_explode.c
+++ b/source/blender/modifiers/intern/MOD_explode.c
@@ -48,6 +48,7 @@
#include "BKE_lattice.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
+#include "BKE_particle.h"
#include "BKE_scene.h"
@@ -93,10 +94,950 @@ static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
return dataMask;
}
-static DerivedMesh *applyModifier(ModifierData *UNUSED(md), Object *UNUSED(ob),
+static void createFacepa(ExplodeModifierData *emd,
+ ParticleSystemModifierData *psmd,
+ DerivedMesh *dm)
+{
+ ParticleSystem *psys = psmd->psys;
+ MFace *fa = NULL, *mface = NULL;
+ MVert *mvert = NULL;
+ ParticleData *pa;
+ KDTree *tree;
+ RNG *rng;
+ float center[3], co[3];
+ int *facepa = NULL, *vertpa = NULL, totvert = 0, totface = 0, totpart = 0;
+ int i, p, v1, v2, v3, v4 = 0;
+
+ mvert = dm->getVertArray(dm);
+ mface = dm->getTessFaceArray(dm);
+ totface = dm->getNumTessFaces(dm);
+ totvert = dm->getNumVerts(dm);
+ totpart = psmd->psys->totpart;
+
+ rng = BLI_rng_new_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);
+ if (dvert) {
+ const int defgrp_index = emd->vgroup - 1;
+ for (i = 0; i < totvert; i++, dvert++) {
+ float val = BLI_rng_get_float(rng);
+ 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_emitter(psmd, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, NULL, NULL, NULL, NULL, NULL);
+ BLI_kdtree_insert(tree, p, co);
+ }
+ 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_v3(center, mvert[fa->v3].co);
+ if (fa->v4) {
+ add_v3_v3(center, mvert[fa->v4].co);
+ mul_v3_fl(center, 0.25);
+ }
+ else
+ mul_v3_fl(center, 1.0f / 3.0f);
+
+ p = BLI_kdtree_find_nearest(tree, center, 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);
+
+ BLI_rng_free(rng);
+}
+
+static int edgecut_get(EdgeHash *edgehash, unsigned int v1, unsigned int v2)
+{
+ return GET_INT_FROM_POINTER(BLI_edgehash_lookup(edgehash, v1, v2));
+}
+
+
+static const short add_faces[24] = {
+ 0,
+ 0, 0, 2, 0, 1, 2, 2, 0, 2, 1,
+ 2, 2, 2, 2, 3, 0, 0, 0, 1, 0,
+ 1, 1, 2
+};
+
+static MFace *get_dface(DerivedMesh *dm, DerivedMesh *split, int cur, int i, MFace *mf)
+{
+ MFace *df = CDDM_get_tessface(split, cur);
+ DM_copy_tessface_data(dm, split, i, cur, 1);
+ *df = *mf;
+ return df;
+}
+
+#define SET_VERTS(a, b, c, d) \
+ { \
+ v[0] = mf->v##a; uv[0] = a - 1; \
+ v[1] = mf->v##b; uv[1] = b - 1; \
+ v[2] = mf->v##c; uv[2] = c - 1; \
+ v[3] = mf->v##d; uv[3] = d - 1; \
+ } (void)0
+
+#define GET_ES(v1, v2) edgecut_get(eh, v1, v2)
+#define INT_UV(uvf, c0, c1) mid_v2_v2v2(uvf, mf->uv[c0], mf->uv[c1])
+
+static void remap_faces_3_6_9_12(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3, int v4)
+{
+ MFace *df1 = get_dface(dm, split, cur, i, mf);
+ MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
+ MFace *df3 = get_dface(dm, split, cur + 2, i, mf);
+
+ facepa[cur] = vertpa[v1];
+ df1->v1 = v1;
+ df1->v2 = GET_ES(v1, v2);
+ df1->v3 = GET_ES(v2, v3);
+ df1->v4 = v3;
+ df1->flag |= ME_FACE_SEL;
+
+ facepa[cur + 1] = vertpa[v2];
+ df2->v1 = GET_ES(v1, v2);
+ df2->v2 = v2;
+ df2->v3 = GET_ES(v2, v3);
+ df2->v4 = 0;
+ df2->flag &= ~ME_FACE_SEL;
+
+ facepa[cur + 2] = vertpa[v1];
+ df3->v1 = v1;
+ df3->v2 = v3;
+ df3->v3 = v4;
+ df3->v4 = 0;
+ df3->flag &= ~ME_FACE_SEL;
+}
+
+static void remap_uvs_3_6_9_12(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
+{
+ MTFace *mf, *df1, *df2, *df3;
+ int l;
+
+ for (l = 0; l < numlayer; l++) {
+ mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
+ df1 = mf + cur;
+ df2 = df1 + 1;
+ df3 = df1 + 2;
+ mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
+ mf += i;
+
+ copy_v2_v2(df1->uv[0], mf->uv[c0]);
+ INT_UV(df1->uv[1], c0, c1);
+ INT_UV(df1->uv[2], c1, c2);
+ copy_v2_v2(df1->uv[3], mf->uv[c2]);
+
+ INT_UV(df2->uv[0], c0, c1);
+ copy_v2_v2(df2->uv[1], mf->uv[c1]);
+ INT_UV(df2->uv[2], c1, c2);
+
+ copy_v2_v2(df3->uv[0], mf->uv[c0]);
+ copy_v2_v2(df3->uv[1], mf->uv[c2]);
+ copy_v2_v2(df3->uv[2], mf->uv[c3]);
+ }
+}
+
+static void remap_faces_5_10(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3, int v4)
+{
+ MFace *df1 = get_dface(dm, split, cur, i, mf);
+ MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
+
+ facepa[cur] = vertpa[v1];
+ df1->v1 = v1;
+ df1->v2 = v2;
+ df1->v3 = GET_ES(v2, v3);
+ df1->v4 = GET_ES(v1, v4);
+ df1->flag |= ME_FACE_SEL;
+
+ facepa[cur + 1] = vertpa[v3];
+ df2->v1 = GET_ES(v1, v4);
+ df2->v2 = GET_ES(v2, v3);
+ df2->v3 = v3;
+ df2->v4 = v4;
+ df2->flag |= ME_FACE_SEL;
+}
+
+static void remap_uvs_5_10(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
+{
+ MTFace *mf, *df1, *df2;
+ int l;
+
+ for (l = 0; l < numlayer; l++) {
+ mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
+ df1 = mf + cur;
+ df2 = df1 + 1;
+ mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
+ mf += i;
+
+ copy_v2_v2(df1->uv[0], mf->uv[c0]);
+ copy_v2_v2(df1->uv[1], mf->uv[c1]);
+ INT_UV(df1->uv[2], c1, c2);
+ INT_UV(df1->uv[3], c0, c3);
+
+ INT_UV(df2->uv[0], c0, c3);
+ INT_UV(df2->uv[1], c1, c2);
+ copy_v2_v2(df2->uv[2], mf->uv[c2]);
+ copy_v2_v2(df2->uv[3], mf->uv[c3]);
+
+ }
+}
+
+static void remap_faces_15(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3, int v4)
+{
+ MFace *df1 = get_dface(dm, split, cur, i, mf);
+ MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
+ MFace *df3 = get_dface(dm, split, cur + 2, i, mf);
+ MFace *df4 = get_dface(dm, split, cur + 3, i, mf);
+
+ facepa[cur] = vertpa[v1];
+ df1->v1 = v1;
+ df1->v2 = GET_ES(v1, v2);
+ df1->v3 = GET_ES(v1, v3);
+ df1->v4 = GET_ES(v1, v4);
+ df1->flag |= ME_FACE_SEL;
+
+ facepa[cur + 1] = vertpa[v2];
+ df2->v1 = GET_ES(v1, v2);
+ df2->v2 = v2;
+ df2->v3 = GET_ES(v2, v3);
+ df2->v4 = GET_ES(v1, v3);
+ df2->flag |= ME_FACE_SEL;
+
+ facepa[cur + 2] = vertpa[v3];
+ df3->v1 = GET_ES(v1, v3);
+ df3->v2 = GET_ES(v2, v3);
+ df3->v3 = v3;
+ df3->v4 = GET_ES(v3, v4);
+ df3->flag |= ME_FACE_SEL;
+
+ facepa[cur + 3] = vertpa[v4];
+ df4->v1 = GET_ES(v1, v4);
+ df4->v2 = GET_ES(v1, v3);
+ df4->v3 = GET_ES(v3, v4);
+ df4->v4 = v4;
+ df4->flag |= ME_FACE_SEL;
+}
+
+static void remap_uvs_15(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
+{
+ MTFace *mf, *df1, *df2, *df3, *df4;
+ int l;
+
+ for (l = 0; l < numlayer; l++) {
+ mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
+ df1 = mf + cur;
+ df2 = df1 + 1;
+ df3 = df1 + 2;
+ df4 = df1 + 3;
+ mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
+ mf += i;
+
+ copy_v2_v2(df1->uv[0], mf->uv[c0]);
+ INT_UV(df1->uv[1], c0, c1);
+ INT_UV(df1->uv[2], c0, c2);
+ INT_UV(df1->uv[3], c0, c3);
+
+ INT_UV(df2->uv[0], c0, c1);
+ copy_v2_v2(df2->uv[1], mf->uv[c1]);
+ INT_UV(df2->uv[2], c1, c2);
+ INT_UV(df2->uv[3], c0, c2);
+
+ INT_UV(df3->uv[0], c0, c2);
+ INT_UV(df3->uv[1], c1, c2);
+ copy_v2_v2(df3->uv[2], mf->uv[c2]);
+ INT_UV(df3->uv[3], c2, c3);
+
+ INT_UV(df4->uv[0], c0, c3);
+ INT_UV(df4->uv[1], c0, c2);
+ INT_UV(df4->uv[2], c2, c3);
+ copy_v2_v2(df4->uv[3], mf->uv[c3]);
+ }
+}
+
+static void remap_faces_7_11_13_14(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3, int v4)
+{
+ MFace *df1 = get_dface(dm, split, cur, i, mf);
+ MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
+ MFace *df3 = get_dface(dm, split, cur + 2, i, mf);
+
+ facepa[cur] = vertpa[v1];
+ df1->v1 = v1;
+ df1->v2 = GET_ES(v1, v2);
+ df1->v3 = GET_ES(v2, v3);
+ df1->v4 = GET_ES(v1, v4);
+ df1->flag |= ME_FACE_SEL;
+
+ facepa[cur + 1] = vertpa[v2];
+ df2->v1 = GET_ES(v1, v2);
+ df2->v2 = v2;
+ df2->v3 = GET_ES(v2, v3);
+ df2->v4 = 0;
+ df2->flag &= ~ME_FACE_SEL;
+
+ facepa[cur + 2] = vertpa[v4];
+ df3->v1 = GET_ES(v1, v4);
+ df3->v2 = GET_ES(v2, v3);
+ df3->v3 = v3;
+ df3->v4 = v4;
+ df3->flag |= ME_FACE_SEL;
+}
+
+static void remap_uvs_7_11_13_14(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2, int c3)
+{
+ MTFace *mf, *df1, *df2, *df3;
+ int l;
+
+ for (l = 0; l < numlayer; l++) {
+ mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
+ df1 = mf + cur;
+ df2 = df1 + 1;
+ df3 = df1 + 2;
+ mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
+ mf += i;
+
+ copy_v2_v2(df1->uv[0], mf->uv[c0]);
+ INT_UV(df1->uv[1], c0, c1);
+ INT_UV(df1->uv[2], c1, c2);
+ INT_UV(df1->uv[3], c0, c3);
+
+ INT_UV(df2->uv[0], c0, c1);
+ copy_v2_v2(df2->uv[1], mf->uv[c1]);
+ INT_UV(df2->uv[2], c1, c2);
+
+ INT_UV(df3->uv[0], c0, c3);
+ INT_UV(df3->uv[1], c1, c2);
+ copy_v2_v2(df3->uv[2], mf->uv[c2]);
+ copy_v2_v2(df3->uv[3], mf->uv[c3]);
+ }
+}
+
+static void remap_faces_19_21_22(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3)
+{
+ MFace *df1 = get_dface(dm, split, cur, i, mf);
+ MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
+
+ facepa[cur] = vertpa[v1];
+ df1->v1 = v1;
+ df1->v2 = GET_ES(v1, v2);
+ df1->v3 = GET_ES(v1, v3);
+ df1->v4 = 0;
+ df1->flag &= ~ME_FACE_SEL;
+
+ facepa[cur + 1] = vertpa[v2];
+ df2->v1 = GET_ES(v1, v2);
+ df2->v2 = v2;
+ df2->v3 = v3;
+ df2->v4 = GET_ES(v1, v3);
+ df2->flag |= ME_FACE_SEL;
+}
+
+static void remap_uvs_19_21_22(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2)
+{
+ MTFace *mf, *df1, *df2;
+ int l;
+
+ for (l = 0; l < numlayer; l++) {
+ mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
+ df1 = mf + cur;
+ df2 = df1 + 1;
+ mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
+ mf += i;
+
+ copy_v2_v2(df1->uv[0], mf->uv[c0]);
+ INT_UV(df1->uv[1], c0, c1);
+ INT_UV(df1->uv[2], c0, c2);
+
+ INT_UV(df2->uv[0], c0, c1);
+ copy_v2_v2(df2->uv[1], mf->uv[c1]);
+ copy_v2_v2(df2->uv[2], mf->uv[c2]);
+ INT_UV(df2->uv[3], c0, c2);
+ }
+}
+
+static void remap_faces_23(DerivedMesh *dm, DerivedMesh *split, MFace *mf, int *facepa, int *vertpa, int i, EdgeHash *eh, int cur, int v1, int v2, int v3)
+{
+ MFace *df1 = get_dface(dm, split, cur, i, mf);
+ MFace *df2 = get_dface(dm, split, cur + 1, i, mf);
+ MFace *df3 = get_dface(dm, split, cur + 2, i, mf);
+
+ facepa[cur] = vertpa[v1];
+ df1->v1 = v1;
+ df1->v2 = GET_ES(v1, v2);
+ df1->v3 = GET_ES(v2, v3);
+ df1->v4 = GET_ES(v1, v3);
+ df1->flag |= ME_FACE_SEL;
+
+ facepa[cur + 1] = vertpa[v2];
+ df2->v1 = GET_ES(v1, v2);
+ df2->v2 = v2;
+ df2->v3 = GET_ES(v2, v3);
+ df2->v4 = 0;
+ df2->flag &= ~ME_FACE_SEL;
+
+ facepa[cur + 2] = vertpa[v3];
+ df3->v1 = GET_ES(v1, v3);
+ df3->v2 = GET_ES(v2, v3);
+ df3->v3 = v3;
+ df3->v4 = 0;
+ df3->flag &= ~ME_FACE_SEL;
+}
+
+static void remap_uvs_23(DerivedMesh *dm, DerivedMesh *split, int numlayer, int i, int cur, int c0, int c1, int c2)
+{
+ MTFace *mf, *df1, *df2;
+ int l;
+
+ for (l = 0; l < numlayer; l++) {
+ mf = CustomData_get_layer_n(&split->faceData, CD_MTFACE, l);
+ df1 = mf + cur;
+ df2 = df1 + 1;
+ mf = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, l);
+ mf += i;
+
+ copy_v2_v2(df1->uv[0], mf->uv[c0]);
+ INT_UV(df1->uv[1], c0, c1);
+ INT_UV(df1->uv[2], c1, c2);
+ INT_UV(df1->uv[3], c0, c2);
+
+ INT_UV(df2->uv[0], c0, c1);
+ copy_v2_v2(df2->uv[1], mf->uv[c1]);
+ INT_UV(df2->uv[2], c1, c2);
+
+ INT_UV(df2->uv[0], c0, c2);
+ INT_UV(df2->uv[1], c1, c2);
+ copy_v2_v2(df2->uv[2], mf->uv[c2]);
+ }
+}
+
+static DerivedMesh *cutEdges(ExplodeModifierData *emd, DerivedMesh *dm)
+{
+ DerivedMesh *splitdm;
+ MFace *mf = NULL, *df1 = NULL;
+ MFace *mface = dm->getTessFaceArray(dm);
+ MVert *dupve, *mv;
+ EdgeHash *edgehash;
+ EdgeHashIterator *ehi;
+ int totvert = dm->getNumVerts(dm);
+ int totface = dm->getNumTessFaces(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, curdupface = 0;
+ int i, v1, v2, v3, v4, esplit,
+ v[4] = {0, 0, 0, 0}, /* To quite gcc barking... */
+ uv[4] = {0, 0, 0, 0}; /* To quite gcc barking... */
+ int numlayer;
+ unsigned int ed_v1, ed_v2;
+
+ edgehash = BLI_edgehash_new(__func__);
+
+ /* 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++) {
+ v1 = vertpa[mf->v1];
+ v2 = vertpa[mf->v2];
+ v3 = vertpa[mf->v3];
+
+ if (v1 != v2) {
+ BLI_edgehash_reinsert(edgehash, mf->v1, mf->v2, NULL);
+ (*fs) |= 1;
+ }
+
+ if (v2 != v3) {
+ BLI_edgehash_reinsert(edgehash, mf->v2, mf->v3, NULL);
+ (*fs) |= 2;
+ }
+
+ if (mf->v4) {
+ v4 = vertpa[mf->v4];
+
+ if (v3 != v4) {
+ BLI_edgehash_reinsert(edgehash, mf->v3, mf->v4, NULL);
+ (*fs) |= 4;
+ }
+
+ if (v1 != v4) {
+ BLI_edgehash_reinsert(edgehash, mf->v1, mf->v4, NULL);
+ (*fs) |= 8;
+ }
+
+ /* mark center vertex as a fake edge split */
+ if (*fs == 15)
+ BLI_edgehash_reinsert(edgehash, mf->v1, mf->v3, NULL);
+ }
+ else {
+ (*fs) |= 16; /* mark face as tri */
+
+ if (v1 != v3) {
+ BLI_edgehash_reinsert(edgehash, mf->v1, mf->v3, NULL);
+ (*fs) |= 4;
+ }
+ }
+ }
+
+ /* count splits & create indexes for new verts */
+ 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++)
+ totfsplit += add_faces[*fs];
+
+ splitdm = CDDM_from_template_ex(
+ dm, totesplit, 0, totface + totfsplit, 0, 0,
+ CD_MASK_DERIVEDMESH | CD_MASK_FACECORNERS);
+ numlayer = CustomData_number_of_layers(&splitdm->faceData, CD_MTFACE);
+
+ /* 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;
+ }
+
+ /* override original facepa (original pointer is saved in caller function) */
+
+ /* BMESH_TODO, (totfsplit * 2) over allocation is used since the quads are
+ * later interpreted as tri's, for this to work right I think we probably
+ * have to stop using tessface - campbell */
+
+ facepa = MEM_callocN(sizeof(int) * (totface + (totfsplit * 2)), "explode_facepa");
+ //memcpy(facepa, emd->facepa, totface*sizeof(int));
+ emd->facepa = facepa;
+
+ /* create new verts */
+ ehi = BLI_edgehashIterator_new(edgehash);
+ for (; !BLI_edgehashIterator_isDone(ehi); BLI_edgehashIterator_step(ehi)) {
+ BLI_edgehashIterator_getKey(ehi, &ed_v1, &ed_v2);
+ esplit = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
+ mv = CDDM_get_vert(splitdm, ed_v2);
+ dupve = CDDM_get_vert(splitdm, esplit);
+
+ DM_copy_vert_data(splitdm, splitdm, ed_v2, esplit, 1);
+
+ *dupve = *mv;
+
+ mv = CDDM_get_vert(splitdm, ed_v1);
+
+ mid_v3_v3v3(dupve->co, dupve->co, mv->co);
+ }
+ BLI_edgehashIterator_free(ehi);
+
+ /* create new faces */
+ curdupface = 0; //=totface;
+ //curdupin=totesplit;
+ for (i = 0, fs = facesplit; i < totface; i++, fs++) {
+ mf = dm->getTessFaceData(dm, i, CD_MFACE);
+
+ switch (*fs) {
+ case 3:
+ case 10:
+ case 11:
+ case 15:
+ SET_VERTS(1, 2, 3, 4);
+ break;
+ case 5:
+ case 6:
+ case 7:
+ SET_VERTS(2, 3, 4, 1);
+ break;
+ case 9:
+ case 13:
+ SET_VERTS(4, 1, 2, 3);
+ break;
+ case 12:
+ case 14:
+ SET_VERTS(3, 4, 1, 2);
+ break;
+ case 21:
+ case 23:
+ SET_VERTS(1, 2, 3, 4);
+ break;
+ case 19:
+ SET_VERTS(2, 3, 1, 4);
+ break;
+ case 22:
+ SET_VERTS(3, 1, 2, 4);
+ break;
+ }
+
+ switch (*fs) {
+ case 3:
+ case 6:
+ case 9:
+ case 12:
+ remap_faces_3_6_9_12(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
+ if (numlayer)
+ remap_uvs_3_6_9_12(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
+ break;
+ case 5:
+ case 10:
+ remap_faces_5_10(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
+ if (numlayer)
+ remap_uvs_5_10(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
+ break;
+ case 15:
+ remap_faces_15(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
+ if (numlayer)
+ remap_uvs_15(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
+ break;
+ case 7:
+ case 11:
+ case 13:
+ case 14:
+ remap_faces_7_11_13_14(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2], v[3]);
+ if (numlayer)
+ remap_uvs_7_11_13_14(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2], uv[3]);
+ break;
+ case 19:
+ case 21:
+ case 22:
+ remap_faces_19_21_22(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2]);
+ if (numlayer)
+ remap_uvs_19_21_22(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2]);
+ break;
+ case 23:
+ remap_faces_23(dm, splitdm, mf, facepa, vertpa, i, edgehash, curdupface, v[0], v[1], v[2]);
+ if (numlayer)
+ remap_uvs_23(dm, splitdm, numlayer, i, curdupface, uv[0], uv[1], uv[2]);
+ break;
+ case 0:
+ case 16:
+ df1 = get_dface(dm, splitdm, curdupface, i, mf);
+ facepa[curdupface] = vertpa[mf->v1];
+
+ if (df1->v4)
+ df1->flag |= ME_FACE_SEL;
+ else
+ df1->flag &= ~ME_FACE_SEL;
+ break;
+ }
+
+ curdupface += add_faces[*fs] + 1;
+ }
+
+ for (i = 0; i < curdupface; i++) {
+ mf = CDDM_get_tessface(splitdm, i);
+ test_index_face(mf, &splitdm->faceData, i, ((mf->flag & ME_FACE_SEL) ? 4 : 3));
+ }
+
+ BLI_edgehash_free(edgehash, NULL);
+ MEM_freeN(facesplit);
+ MEM_freeN(vertpa);
+
+ CDDM_calc_edges_tessface(splitdm);
+ CDDM_tessfaces_to_faces(splitdm); /*builds ngon faces from tess (mface) faces*/
+
+ return splitdm;
+}
+static DerivedMesh *explodeMesh(ExplodeModifierData *emd,
+ ParticleSystemModifierData *psmd, Scene *scene, Object *ob,
+ DerivedMesh *to_explode)
+{
+ DerivedMesh *explode, *dm = to_explode;
+ MFace *mf = NULL, *mface;
+ /* ParticleSettings *part=psmd->psys->part; */ /* UNUSED */
+ ParticleSimulationData sim = {NULL};
+ ParticleData *pa = NULL, *pars = psmd->psys->particles;
+ ParticleKey state, birth;
+ EdgeHash *vertpahash;
+ EdgeHashIterator *ehi;
+ float *vertco = NULL, imat[4][4];
+ float rot[4];
+ float cfra;
+ /* float timestep; */
+ const int *facepa = emd->facepa;
+ int totdup = 0, totvert = 0, totface = 0, totpart = 0, delface = 0;
+ int i, v, u;
+ unsigned int ed_v1, ed_v2, mindex = 0;
+ MTFace *mtface = NULL, *mtf;
+
+ totface = dm->getNumTessFaces(dm);
+ totvert = dm->getNumVerts(dm);
+ mface = dm->getTessFaceArray(dm);
+ totpart = psmd->psys->totpart;
+
+ sim.scene = scene;
+ sim.ob = ob;
+ sim.psys = psmd->psys;
+ sim.psmd = psmd;
+
+ /* timestep = psys_get_timestep(&sim); */
+
+ cfra = BKE_scene_frame_get(scene);
+
+ /* hash table for vertice <-> particle relations */
+ vertpahash = BLI_edgehash_new(__func__);
+
+ for (i = 0; i < totface; i++) {
+ if (facepa[i] != totpart) {
+ pa = pars + facepa[i];
+
+ if ((pa->alive == PARS_UNBORN && (emd->flag & eExplodeFlag_Unborn) == 0) ||
+ (pa->alive == PARS_ALIVE && (emd->flag & eExplodeFlag_Alive) == 0) ||
+ (pa->alive == PARS_DEAD && (emd->flag & eExplodeFlag_Dead) == 0))
+ {
+ delface++;
+ continue;
+ }
+ }
+
+ /* 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_reinsert(vertpahash, mf->v1, mindex, NULL);
+ BLI_edgehash_reinsert(vertpahash, mf->v2, mindex, NULL);
+ BLI_edgehash_reinsert(vertpahash, mf->v3, mindex, NULL);
+ if (mf->v4)
+ BLI_edgehash_reinsert(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_ex(dm, totdup, 0, totface - delface, 0, 0, CD_MASK_DERIVEDMESH | CD_MASK_FACECORNERS);
+ mtface = CustomData_get_layer_named(&explode->faceData, CD_MTFACE, emd->uvname);
+ /*dupvert = CDDM_get_verts(explode);*/
+
+ /* getting back to object space */
+ invert_m4_m4(imat, ob->obmat);
+
+ psmd->psys->lattice_deform_data = psys_create_lattice_deform_data(&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, &ed_v1, &ed_v2);
+ ed_v2 -= totvert;
+ v = GET_INT_FROM_POINTER(BLI_edgehashIterator_getValue(ehi));
+
+ dm->getVert(dm, ed_v1, &source);
+ dest = CDDM_get_vert(explode, v);
+
+ DM_copy_vert_data(dm, explode, ed_v1, v, 1);
+ *dest = source;
+
+ if (ed_v2 != totpart) {
+ /* get particle */
+ pa = pars + ed_v2;
+
+ psys_get_birth_coords(&sim, pa, &birth, 0, 0);
+
+ state.time = cfra;
+ psys_get_particle_state(&sim, ed_v2, &state, 1);
+
+ vertco = CDDM_get_vert(explode, v)->co;
+ mul_m4_v3(ob->obmat, vertco);
+
+ sub_v3_v3(vertco, birth.co);
+
+ /* apply rotation, size & location */
+ sub_qt_qtqt(rot, state.rot, birth.rot);
+ mul_qt_v3(rot, vertco);
+
+ if (emd->flag & eExplodeFlag_PaSize)
+ mul_v3_fl(vertco, pa->size);
+
+ add_v3_v3(vertco, state.co);
+
+ mul_m4_v3(imat, vertco);
+ }
+ }
+ BLI_edgehashIterator_free(ehi);
+
+ /*map new vertices to faces*/
+ for (i = 0, u = 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->getTessFace(dm, i, &source);
+ mf = CDDM_get_tessface(explode, u);
+
+ orig_v4 = source.v4;
+
+ if (facepa[i] != totpart && cfra < pa->time)
+ mindex = totvert + totpart;
+ else
+ mindex = totvert + facepa[i];
+
+ source.v1 = edgecut_get(vertpahash, source.v1, mindex);
+ source.v2 = edgecut_get(vertpahash, source.v2, mindex);
+ source.v3 = edgecut_get(vertpahash, source.v3, mindex);
+ if (source.v4)
+ source.v4 = edgecut_get(vertpahash, source.v4, mindex);
+
+ DM_copy_tessface_data(dm, explode, i, u, 1);
+
+ *mf = source;
+
+ /* override uv channel for particle age */
+ if (mtface) {
+ float age = (cfra - pa->time) / pa->lifetime;
+ /* Clamp to this range to avoid flipping to the other side of the coordinates. */
+ CLAMP(age, 0.001f, 0.999f);
+
+ mtf = mtface + u;
+
+ mtf->uv[0][0] = mtf->uv[1][0] = mtf->uv[2][0] = mtf->uv[3][0] = age;
+ mtf->uv[0][1] = mtf->uv[1][1] = mtf->uv[2][1] = mtf->uv[3][1] = 0.5f;
+ }
+
+ test_index_face(mf, &explode->faceData, u, (orig_v4 ? 4 : 3));
+ u++;
+ }
+
+ /* cleanup */
+ BLI_edgehash_free(vertpahash, NULL);
+
+ /* finalization */
+ CDDM_calc_edges_tessface(explode);
+ CDDM_tessfaces_to_faces(explode);
+ explode->dirty |= DM_DIRTY_NORMALS;
+
+ if (psmd->psys->lattice_deform_data) {
+ end_latt_deform(psmd->psys->lattice_deform_data);
+ psmd->psys->lattice_deform_data = NULL;
+ }
+
+ return explode;
+}
+
+static ParticleSystemModifierData *findPrecedingParticlesystem(Object *ob, ModifierData *emd)
+{
+ ModifierData *md;
+ ParticleSystemModifierData *psmd = NULL;
+
+ 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,
ModifierApplyFlag UNUSED(flag))
{
+ DerivedMesh *dm = derivedData;
+ ExplodeModifierData *emd = (ExplodeModifierData *) md;
+ ParticleSystemModifierData *psmd = findPrecedingParticlesystem(ob, md);
+
+ DM_ensure_tessface(dm); /* BMESH - UNTIL MODIFIER IS UPDATED FOR MPoly */
+
+ if (psmd) {
+ ParticleSystem *psys = psmd->psys;
+
+ if (psys == NULL || psys->totpart == 0) return derivedData;
+ if (psys->part == NULL || psys->particles == NULL) return derivedData;
+ if (psmd->dm_final == NULL) return derivedData;
+
+ /* 1. find faces to be exploded if needed */
+ if (emd->facepa == NULL ||
+ psmd->flag & eParticleSystemFlag_Pars ||
+ emd->flag & eExplodeFlag_CalcFaces ||
+ MEM_allocN_len(emd->facepa) / sizeof(int) != dm->getNumTessFaces(dm))
+ {
+ if (psmd->flag & eParticleSystemFlag_Pars)
+ psmd->flag &= ~eParticleSystemFlag_Pars;
+
+ if (emd->flag & eExplodeFlag_CalcFaces)
+ emd->flag &= ~eExplodeFlag_CalcFaces;
+
+ createFacepa(emd, psmd, derivedData);
+ }
+ /* 2. create new mesh */
+ if (emd->flag & eExplodeFlag_EdgeCut) {
+ int *facepa = emd->facepa;
+ DerivedMesh *splitdm = cutEdges(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;
}
diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c
index 5439f77aede..ce3fdc4bbe8 100644
--- a/source/blender/modifiers/intern/MOD_laplaciandeform.c
+++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c
@@ -33,12 +33,11 @@
#include "BLI_math.h"
#include "BLI_string.h"
-#include "DNA_object_types.h"
-
#include "MEM_guardedalloc.h"
#include "BKE_mesh_mapping.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_particle.h"
#include "BKE_deform.h"
#include "MOD_util.h"
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
new file mode 100644
index 00000000000..4e78e758dc3
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -0,0 +1,470 @@
+/*
+ * ***** 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 *****
+ *
+ */
+
+/** \file blender/modifiers/intern/MOD_particleinstance.c
+ * \ingroup modifiers
+ */
+
+
+#include "DNA_meshdata_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_listbase.h"
+#include "BLI_rand.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_effect.h"
+#include "BKE_global.h"
+#include "BKE_lattice.h"
+#include "BKE_library_query.h"
+#include "BKE_modifier.h"
+#include "BKE_particle.h"
+#include "BKE_pointcache.h"
+
+#include "depsgraph_private.h"
+#include "DEG_depsgraph_build.h"
+
+static void initData(ModifierData *md)
+{
+ ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
+
+ pimd->flag = eParticleInstanceFlag_Parents | eParticleInstanceFlag_Unborn |
+ eParticleInstanceFlag_Alive | eParticleInstanceFlag_Dead;
+ pimd->psys = 1;
+ pimd->position = 1.0f;
+ pimd->axis = 2;
+
+}
+static void copyData(ModifierData *md, ModifierData *target)
+{
+#if 0
+ ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
+ ParticleInstanceModifierData *tpimd = (ParticleInstanceModifierData *) target;
+#endif
+ modifier_copyData_generic(md, target);
+}
+
+static bool isDisabled(ModifierData *md, int useRenderParams)
+{
+ ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
+ ParticleSystem *psys;
+ ModifierData *ob_md;
+
+ if (!pimd->ob)
+ return true;
+
+ psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
+ if (psys == NULL)
+ return true;
+
+ /* If the psys modifier is disabled we cannot use its data.
+ * First look up the psys modifier from the object, then check if it is enabled.
+ */
+ for (ob_md = pimd->ob->modifiers.first; ob_md; ob_md = ob_md->next) {
+ if (ob_md->type == eModifierType_ParticleSystem) {
+ ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)ob_md;
+ if (psmd->psys == psys) {
+ int required_mode;
+
+ if (useRenderParams) required_mode = eModifierMode_Render;
+ else required_mode = eModifierMode_Realtime;
+
+ if (!modifier_isEnabled(md->scene, ob_md, required_mode))
+ return true;
+
+ break;
+ }
+ }
+ }
+
+ return false;
+}
+
+
+static void updateDepgraph(ModifierData *md, DagForest *forest,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(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,
+ "Particle Instance Modifier");
+ }
+}
+
+static void updateDepsgraph(ModifierData *md,
+ struct Main *UNUSED(bmain),
+ struct Scene *UNUSED(scene),
+ Object *UNUSED(ob),
+ struct DepsNodeHandle *node)
+{
+ ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
+ if (pimd->ob != NULL) {
+ DEG_add_object_relation(node, pimd->ob, DEG_OB_COMP_TRANSFORM, "Particle Instance Modifier");
+ }
+}
+
+static void foreachObjectLink(ModifierData *md, Object *ob,
+ ObjectWalkFunc walk, void *userData)
+{
+ ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
+
+ walk(userData, ob, &pimd->ob, IDWALK_NOP);
+}
+
+static int particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
+{
+ ParticleData *pa;
+
+ if (pimd->flag & eParticleInstanceFlag_Parents) {
+ if (p >= psys->totpart) {
+ if (psys->part->childtype == PART_CHILD_PARTICLES) {
+ pa = psys->particles + (psys->child + p - psys->totpart)->parent;
+ }
+ else {
+ pa = NULL;
+ }
+ }
+ else {
+ pa = psys->particles + p;
+ }
+ }
+ else {
+ if (psys->part->childtype == PART_CHILD_PARTICLES) {
+ pa = psys->particles + (psys->child + p)->parent;
+ }
+ else {
+ pa = NULL;
+ }
+ }
+
+ if (pa) {
+ if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) return 1;
+ if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) return 1;
+ if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) return 1;
+ }
+
+ return 0;
+}
+
+static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
+ DerivedMesh *derivedData,
+ ModifierApplyFlag UNUSED(flag))
+{
+ DerivedMesh *dm = derivedData, *result;
+ ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
+ ParticleSimulationData sim;
+ ParticleSystem *psys = NULL;
+ ParticleData *pa = NULL;
+ MPoly *mpoly, *orig_mpoly;
+ MLoop *mloop, *orig_mloop;
+ MVert *mvert, *orig_mvert;
+ int totvert, totpoly, totloop /* , totedge */;
+ int maxvert, maxpoly, maxloop, totpart = 0, first_particle = 0;
+ int k, p, p_skip;
+ short track = ob->trackflag % 3, trackneg, axis = pimd->axis;
+ float max_co = 0.0, min_co = 0.0, temp_co[3];
+ float *size = NULL;
+
+ trackneg = ((ob->trackflag > 2) ? 1 : 0);
+
+ if (pimd->ob == ob) {
+ pimd->ob = NULL;
+ return derivedData;
+ }
+
+ if (pimd->ob) {
+ psys = BLI_findlink(&pimd->ob->particlesystem, pimd->psys - 1);
+ if (psys == NULL || 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;
+
+ sim.scene = md->scene;
+ sim.ob = pimd->ob;
+ sim.psys = psys;
+ sim.psmd = psys_get_modifier(pimd->ob, psys);
+
+ if (pimd->flag & eParticleInstanceFlag_UseSize) {
+ float *si;
+ si = size = MEM_callocN(totpart * sizeof(float), "particle size array");
+
+ if (pimd->flag & eParticleInstanceFlag_Parents) {
+ for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++)
+ *si = pa->size;
+ }
+
+ if (pimd->flag & eParticleInstanceFlag_Children) {
+ ChildParticle *cpa = psys->child;
+
+ for (p = 0; p < psys->totchild; p++, cpa++, si++) {
+ *si = psys_get_child_size(psys, cpa, 0.0f, NULL);
+ }
+ }
+ }
+
+ totvert = dm->getNumVerts(dm);
+ totpoly = dm->getNumPolys(dm);
+ totloop = dm->getNumLoops(dm);
+ /* totedge = dm->getNumEdges(dm); */ /* UNUSED */
+
+ /* count particles */
+ maxvert = 0;
+ maxpoly = 0;
+ maxloop = 0;
+
+ for (p = 0; p < totpart; p++) {
+ if (particle_skip(pimd, psys, p))
+ continue;
+
+ maxvert += totvert;
+ maxpoly += totpoly;
+ maxloop += totloop;
+ }
+
+ psys->lattice_deform_data = psys_create_lattice_deform_data(&sim);
+
+ if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) {
+ float min[3], max[3];
+ INIT_MINMAX(min, max);
+ dm->getMinMax(dm, min, max);
+ min_co = min[track];
+ max_co = max[track];
+ }
+
+ result = CDDM_from_template(dm, maxvert, 0, 0, maxloop, maxpoly);
+
+ mvert = result->getVertArray(result);
+ orig_mvert = dm->getVertArray(dm);
+
+ mpoly = result->getPolyArray(result);
+ orig_mpoly = dm->getPolyArray(dm);
+ mloop = result->getLoopArray(result);
+ orig_mloop = dm->getLoopArray(dm);
+
+ for (p = 0, p_skip = 0; p < totpart; p++) {
+ float prev_dir[3];
+ float frame[4]; /* frame orientation quaternion */
+
+ /* skip particle? */
+ if (particle_skip(pimd, psys, p))
+ continue;
+
+ /* set vertices coordinates */
+ for (k = 0; k < totvert; k++) {
+ ParticleKey state;
+ MVert *inMV;
+ MVert *mv = mvert + p_skip * totvert + k;
+
+ inMV = orig_mvert + k;
+ DM_copy_vert_data(dm, result, k, p_skip * totvert + k, 1);
+ *mv = *inMV;
+
+ /*change orientation based on object trackflag*/
+ copy_v3_v3(temp_co, mv->co);
+ mv->co[axis] = temp_co[track];
+ mv->co[(axis + 1) % 3] = temp_co[(track + 1) % 3];
+ mv->co[(axis + 2) % 3] = temp_co[(track + 2) % 3];
+
+ /* get particle state */
+ if ((psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) &&
+ (pimd->flag & eParticleInstanceFlag_Path))
+ {
+ float ran = 0.0f;
+ if (pimd->random_position != 0.0f) {
+ ran = pimd->random_position * BLI_hash_frand(psys->seed + p);
+ }
+
+ if (pimd->flag & eParticleInstanceFlag_KeepShape) {
+ state.time = pimd->position * (1.0f - ran);
+ }
+ else {
+ state.time = (mv->co[axis] - min_co) / (max_co - min_co) * pimd->position * (1.0f - ran);
+
+ if (trackneg)
+ state.time = 1.0f - state.time;
+
+ mv->co[axis] = 0.0;
+ }
+
+ psys_get_particle_on_path(&sim, first_particle + p, &state, 1);
+
+ normalize_v3(state.vel);
+
+ /* Incrementally Rotating Frame (Bishop Frame) */
+ if (k == 0) {
+ float hairmat[4][4];
+ float mat[3][3];
+
+ if (first_particle + p < psys->totpart)
+ pa = psys->particles + first_particle + p;
+ else {
+ ChildParticle *cpa = psys->child + (p - psys->totpart);
+ pa = psys->particles + cpa->parent;
+ }
+ psys_mat_hair_to_global(sim.ob, sim.psmd->dm_final, sim.psys->part->from, pa, hairmat);
+ copy_m3_m4(mat, hairmat);
+ /* to quaternion */
+ mat3_to_quat(frame, mat);
+
+ /* note: direction is same as normal vector currently,
+ * but best to keep this separate so the frame can be
+ * rotated later if necessary
+ */
+ copy_v3_v3(prev_dir, state.vel);
+ }
+ else {
+ float rot[4];
+
+ /* incrementally rotate along bend direction */
+ rotation_between_vecs_to_quat(rot, prev_dir, state.vel);
+ mul_qt_qtqt(frame, rot, frame);
+
+ copy_v3_v3(prev_dir, state.vel);
+ }
+
+ copy_qt_qt(state.rot, frame);
+#if 0
+ /* Absolute Frame (Frenet Frame) */
+ if (state.vel[axis] < -0.9999f || state.vel[axis] > 0.9999f) {
+ unit_qt(state.rot);
+ }
+ else {
+ float cross[3];
+ float temp[3] = {0.0f, 0.0f, 0.0f};
+ temp[axis] = 1.0f;
+
+ cross_v3_v3v3(cross, temp, state.vel);
+
+ /* state.vel[axis] is the only component surviving from a dot product with the axis */
+ axis_angle_to_quat(state.rot, cross, saacos(state.vel[axis]));
+ }
+#endif
+ }
+ else {
+ state.time = -1.0;
+ psys_get_particle_state(&sim, first_particle + p, &state, 1);
+ }
+
+ mul_qt_v3(state.rot, mv->co);
+ if (pimd->flag & eParticleInstanceFlag_UseSize)
+ mul_v3_fl(mv->co, size[p]);
+ add_v3_v3(mv->co, state.co);
+ }
+
+ /* create polys and loops */
+ for (k = 0; k < totpoly; k++) {
+ MPoly *inMP = orig_mpoly + k;
+ MPoly *mp = mpoly + p_skip * totpoly + k;
+
+ DM_copy_poly_data(dm, result, k, p_skip * totpoly + k, 1);
+ *mp = *inMP;
+ mp->loopstart += p_skip * totloop;
+
+ {
+ MLoop *inML = orig_mloop + inMP->loopstart;
+ MLoop *ml = mloop + mp->loopstart;
+ int j = mp->totloop;
+
+ DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j);
+ for (; j; j--, ml++, inML++) {
+ ml->v = inML->v + (p_skip * totvert);
+ }
+ }
+ }
+
+ p_skip++;
+ }
+
+ CDDM_calc_edges(result);
+
+ if (psys->lattice_deform_data) {
+ end_latt_deform(psys->lattice_deform_data);
+ psys->lattice_deform_data = NULL;
+ }
+
+ if (size)
+ MEM_freeN(size);
+
+ result->dirty |= DM_DIRTY_NORMALS;
+
+ return result;
+}
+ModifierTypeInfo modifierType_ParticleInstance = {
+ /* name */ "ParticleInstance",
+ /* structName */ "ParticleInstanceModifierData",
+ /* structSize */ sizeof(ParticleInstanceModifierData),
+ /* type */ eModifierTypeType_Constructive,
+ /* flags */ eModifierTypeFlag_AcceptsMesh |
+ eModifierTypeFlag_SupportsMapping |
+ eModifierTypeFlag_SupportsEditmode |
+ eModifierTypeFlag_EnableInEditmode,
+
+ /* copyData */ copyData,
+ /* deformVerts */ NULL,
+ /* deformMatrices */ NULL,
+ /* deformVertsEM */ NULL,
+ /* deformMatricesEM */ NULL,
+ /* applyModifier */ applyModifier,
+ /* applyModifierEM */ NULL,
+ /* initData */ initData,
+ /* requiredDataMask */ NULL,
+ /* freeData */ NULL,
+ /* isDisabled */ isDisabled,
+ /* updateDepgraph */ updateDepgraph,
+ /* updateDepsgraph */ updateDepsgraph,
+ /* dependsOnTime */ NULL,
+ /* dependsOnNormals */ NULL,
+ /* foreachObjectLink */ foreachObjectLink,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c
new file mode 100644
index 00000000000..d8cccca415c
--- /dev/null
+++ b/source/blender/modifiers/intern/MOD_particlesystem.c
@@ -0,0 +1,241 @@
+/*
+ * ***** 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 *****
+ *
+ */
+
+/** \file blender/modifiers/intern/MOD_particlesystem.c
+ * \ingroup modifiers
+ */
+
+
+#include <stddef.h>
+
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BLI_utildefines.h"
+
+
+#include "BKE_cdderivedmesh.h"
+#include "BKE_modifier.h"
+#include "BKE_particle.h"
+
+#include "MOD_util.h"
+
+
+static void initData(ModifierData *md)
+{
+ ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
+ psmd->psys = NULL;
+ psmd->dm_final = NULL;
+ psmd->dm_deformed = NULL;
+ psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0;
+}
+static void freeData(ModifierData *md)
+{
+ ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
+
+ if (psmd->dm_final) {
+ psmd->dm_final->needsFree = true;
+ psmd->dm_final->release(psmd->dm_final);
+ psmd->dm_final = NULL;
+ if (psmd->dm_deformed) {
+ psmd->dm_deformed->needsFree = true;
+ psmd->dm_deformed->release(psmd->dm_deformed);
+ psmd->dm_deformed = NULL;
+ }
+ }
+
+ /* ED_object_modifier_remove may have freed this first before calling
+ * modifier_free (which calls this function) */
+ if (psmd->psys)
+ psmd->psys->flag |= PSYS_DELETE;
+}
+static void copyData(ModifierData *md, ModifierData *target)
+{
+#if 0
+ ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
+#endif
+ ParticleSystemModifierData *tpsmd = (ParticleSystemModifierData *) target;
+
+ modifier_copyData_generic(md, target);
+
+ tpsmd->dm_final = NULL;
+ tpsmd->dm_deformed = NULL;
+ tpsmd->totdmvert = tpsmd->totdmedge = tpsmd->totdmface = 0;
+}
+
+static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
+{
+ ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
+ return psys_emitter_customdata_mask(psmd->psys);
+}
+
+/* saves the current emitter state for a particle system and calculates particles */
+static void deformVerts(ModifierData *md, Object *ob,
+ DerivedMesh *derivedData,
+ float (*vertexCos)[3],
+ int UNUSED(numVerts),
+ ModifierApplyFlag flag)
+{
+ DerivedMesh *dm = derivedData;
+ ParticleSystemModifierData *psmd = (ParticleSystemModifierData *) md;
+ ParticleSystem *psys = NULL;
+ bool needsFree = false;
+ /* float cfra = BKE_scene_frame_get(md->scene); */ /* UNUSED */
+
+ if (ob->particlesystem.first)
+ psys = psmd->psys;
+ else
+ return;
+
+ if (!psys_check_enabled(ob, psys, (flag & MOD_APPLY_RENDER) != 0))
+ return;
+
+ if (dm == NULL) {
+ dm = get_dm(ob, NULL, NULL, vertexCos, false, true);
+
+ if (!dm)
+ return;
+
+ needsFree = true;
+ }
+
+ /* clear old dm */
+ if (psmd->dm_final) {
+ psmd->dm_final->needsFree = true;
+ psmd->dm_final->release(psmd->dm_final);
+ if (psmd->dm_deformed) {
+ psmd->dm_deformed->needsFree = 1;
+ psmd->dm_deformed->release(psmd->dm_deformed);
+ psmd->dm_deformed = NULL;
+ }
+ }
+ else if (psmd->flag & eParticleSystemFlag_file_loaded) {
+ /* in file read dm just wasn't saved in file so no need to reset everything */
+ psmd->flag &= ~eParticleSystemFlag_file_loaded;
+ }
+ else {
+ /* no dm before, so recalc particles fully */
+ psys->recalc |= PSYS_RECALC_RESET;
+ }
+
+ /* make new dm */
+ psmd->dm_final = CDDM_copy(dm);
+ CDDM_apply_vert_coords(psmd->dm_final, vertexCos);
+ CDDM_calc_normals(psmd->dm_final);
+
+ if (needsFree) {
+ dm->needsFree = true;
+ dm->release(dm);
+ }
+
+ /* protect dm */
+ psmd->dm_final->needsFree = false;
+
+ DM_ensure_tessface(psmd->dm_final);
+
+ if (!psmd->dm_final->deformedOnly) {
+ /* XXX Think we can assume here that if current DM is not only-deformed, ob->deformedOnly has been set.
+ * This is awfully weak though. :| */
+ if (ob->derivedDeform) {
+ psmd->dm_deformed = CDDM_copy(ob->derivedDeform);
+ }
+ else { /* Can happen in some cases, e.g. when rendering from Edit mode... */
+ psmd->dm_deformed = CDDM_from_mesh((Mesh *)ob->data);
+ }
+ DM_ensure_tessface(psmd->dm_deformed);
+ }
+
+ /* report change in mesh structure */
+ if (psmd->dm_final->getNumVerts(psmd->dm_final) != psmd->totdmvert ||
+ psmd->dm_final->getNumEdges(psmd->dm_final) != psmd->totdmedge ||
+ psmd->dm_final->getNumTessFaces(psmd->dm_final) != psmd->totdmface)
+ {
+ psys->recalc |= PSYS_RECALC_RESET;
+
+ psmd->totdmvert = psmd->dm_final->getNumVerts(psmd->dm_final);
+ psmd->totdmedge = psmd->dm_final->getNumEdges(psmd->dm_final);
+ psmd->totdmface = psmd->dm_final->getNumTessFaces(psmd->dm_final);
+ }
+
+ if (!(ob->transflag & OB_NO_PSYS_UPDATE)) {
+ psmd->flag &= ~eParticleSystemFlag_psys_updated;
+ particle_system_update(md->scene, ob, psys, (flag & MOD_APPLY_RENDER) != 0);
+ psmd->flag |= eParticleSystemFlag_psys_updated;
+ }
+}
+
+/* disabled particles in editmode for now, until support for proper derivedmesh
+ * updates is coded */
+#if 0
+static void 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);
+
+ deformVerts(md, ob, dm, vertexCos, numVerts);
+
+ if (!derivedData) dm->release(dm);
+}
+#endif
+
+
+ModifierTypeInfo modifierType_ParticleSystem = {
+ /* name */ "ParticleSystem",
+ /* structName */ "ParticleSystemModifierData",
+ /* structSize */ sizeof(ParticleSystemModifierData),
+ /* type */ eModifierTypeType_OnlyDeform,
+ /* flags */ eModifierTypeFlag_AcceptsMesh |
+ eModifierTypeFlag_SupportsMapping |
+ eModifierTypeFlag_UsesPointCache /* |
+ eModifierTypeFlag_SupportsEditmode |
+ eModifierTypeFlag_EnableInEditmode */,
+
+ /* copyData */ copyData,
+ /* deformVerts */ deformVerts,
+ /* deformVertsEM */ NULL,
+ /* deformMatrices */ NULL,
+ /* deformMatricesEM */ NULL,
+ /* applyModifier */ NULL,
+ /* applyModifierEM */ NULL,
+ /* initData */ initData,
+ /* requiredDataMask */ requiredDataMask,
+ /* freeData */ freeData,
+ /* isDisabled */ NULL,
+ /* updateDepgraph */ NULL,
+ /* updateDepsgraph */ NULL,
+ /* dependsOnTime */ NULL,
+ /* dependsOnNormals */ NULL,
+ /* foreachObjectLink */ NULL,
+ /* foreachIDLink */ NULL,
+ /* foreachTexLink */ NULL,
+};
diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c
index 4ccf9fabf0c..97aae733532 100644
--- a/source/blender/modifiers/intern/MOD_shapekey.c
+++ b/source/blender/modifiers/intern/MOD_shapekey.c
@@ -35,12 +35,12 @@
#include "BLI_math.h"
#include "DNA_key_types.h"
-#include "DNA_object_types.h"
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_key.h"
+#include "BKE_particle.h"
#include "MOD_modifiertypes.h"
diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c
index 66c9f613447..d45c8528510 100644
--- a/source/blender/modifiers/intern/MOD_smooth.c
+++ b/source/blender/modifiers/intern/MOD_smooth.c
@@ -34,7 +34,6 @@
#include "DNA_meshdata_types.h"
-#include "DNA_object_types.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -42,6 +41,7 @@
#include "MEM_guardedalloc.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_particle.h"
#include "BKE_deform.h"
#include "MOD_modifiertypes.h"
diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c
index 101f5a4f619..17adc7f1520 100644
--- a/source/blender/modifiers/intern/MOD_softbody.c
+++ b/source/blender/modifiers/intern/MOD_softbody.c
@@ -34,13 +34,13 @@
#include <stdio.h>
-#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_force.h"
#include "BLI_utildefines.h"
#include "BKE_cdderivedmesh.h"
+#include "BKE_particle.h"
#include "BKE_softbody.h"
#include "depsgraph_private.h"
diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c
index 9eb7e4e83b6..911b6997058 100644
--- a/source/blender/modifiers/intern/MOD_solidify.c
+++ b/source/blender/modifiers/intern/MOD_solidify.c
@@ -32,7 +32,6 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_object_types.h"
#include "MEM_guardedalloc.h"
@@ -43,6 +42,7 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_mesh.h"
+#include "BKE_particle.h"
#include "BKE_deform.h"
#include "MOD_modifiertypes.h"
diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c
index a59ace130e7..93414562ccf 100644
--- a/source/blender/modifiers/intern/MOD_util.c
+++ b/source/blender/modifiers/intern/MOD_util.c
@@ -257,6 +257,8 @@ void modifier_type_init(ModifierTypeInfo *types[])
INIT_TYPE(Boolean);
INIT_TYPE(MeshDeform);
INIT_TYPE(Ocean);
+ INIT_TYPE(ParticleSystem);
+ INIT_TYPE(ParticleInstance);
INIT_TYPE(Explode);
INIT_TYPE(Shrinkwrap);
INIT_TYPE(Fluidsim);