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:
-rw-r--r--release/scripts/startup/bl_ui/properties_data_modifier.py22
-rw-r--r--source/blender/blenloader/intern/versioning_270.c12
-rw-r--r--source/blender/makesdna/DNA_modifier_types.h11
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c95
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c191
5 files changed, 281 insertions, 50 deletions
diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py
index 942882a9053..e3cc08ce3d8 100644
--- a/release/scripts/startup/bl_ui/properties_data_modifier.py
+++ b/release/scripts/startup/bl_ui/properties_data_modifier.py
@@ -711,11 +711,15 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
def PARTICLE_INSTANCE(self, layout, ob, md):
layout.prop(md, "object")
- layout.prop(md, "particle_system_index", text="Particle System")
+ if md.object:
+ layout.prop_search(md, "particle_system", md.object, "particle_systems", text="Particle System")
+ else:
+ layout.prop(md, "particle_system_index", text="Particle System")
split = layout.split()
col = split.column()
col.label(text="Create From:")
+ layout.prop(md, "space", text="")
col.prop(md, "use_normal")
col.prop(md, "use_children")
col.prop(md, "use_size")
@@ -726,6 +730,10 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "show_unborn")
col.prop(md, "show_dead")
+ row = layout.row(align=True)
+ row.prop(md, "particle_amount", text="Amount")
+ row.prop(md, "particle_offset", text="Offset")
+
layout.separator()
layout.prop(md, "use_path", text="Create Along Paths")
@@ -737,8 +745,16 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
col.prop(md, "use_preserve_shape")
col = split.column()
- col.prop(md, "position", slider=True)
- col.prop(md, "random_position", text="Random", slider=True)
+ col2 = col.column(align=True)
+ col2.prop(md, "position", slider=True)
+ col2.prop(md, "random_position", text="Random", slider=True)
+ col2 = col.column(align=True)
+ col2.prop(md, "rotation", slider=True)
+ col2.prop(md, "random_rotation", text="Random", slider=True)
+
+ col = layout.column()
+ col.prop_search(md, "index_layer_name", ob.data, "vertex_colors", text="Index Layer")
+ col.prop_search(md, "value_layer_name", ob.data, "vertex_colors", text="Value Layer")
def PARTICLE_SYSTEM(self, layout, ob, md):
layout.label(text="Settings can be found inside the Particle context")
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index e9de7919d25..86e6071180e 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -1813,6 +1813,18 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
}
scene->r.ffcodecdata.ffmpeg_preset = preset;
}
+
+ if (!DNA_struct_elem_find(fd->filesdna, "ParticleInstanceModifierData", "float", "particle_amount")) {
+ for (Object *ob = main->object.first; ob; ob = ob->id.next) {
+ for (ModifierData *md = ob->modifiers.first; md; md = md->next) {
+ if (md->type == eModifierType_ParticleInstance) {
+ ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
+ pimd->space = eParticleInstanceSpace_World;
+ pimd->particle_amount = 1.0f;
+ }
+ }
+ }
+ }
}
}
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 766dd196562..258acbab31a 100644
--- a/source/blender/makesdna/DNA_modifier_types.h
+++ b/source/blender/makesdna/DNA_modifier_types.h
@@ -753,12 +753,21 @@ typedef enum {
eParticleInstanceFlag_UseSize = (1 << 7),
} ParticleInstanceModifierFlag;
+typedef enum {
+ eParticleInstanceSpace_World = 0,
+ eParticleInstanceSpace_Local = 1,
+} ParticleInstanceModifierSpace;
+
typedef struct ParticleInstanceModifierData {
ModifierData modifier;
struct Object *ob;
- short psys, flag, axis, pad;
+ short psys, flag, axis, space;
float position, random_position;
+ float rotation, random_rotation;
+ float particle_amount, particle_offset;
+ char index_layer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
+ char value_layer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */
} ParticleInstanceModifierData;
typedef enum {
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index 2f92c47eed9..0ebd29b200c 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1155,6 +1155,43 @@ static void rna_MeshSequenceCache_object_path_update(Main *bmain, Scene *scene,
rna_Modifier_update(bmain, scene, ptr);
}
+static int rna_ParticleInstanceModifier_particle_system_poll(PointerRNA *ptr, const PointerRNA value)
+{
+ ParticleInstanceModifierData *psmd = ptr->data;
+ ParticleSystem *psys = value.data;
+
+ if (!psmd->ob)
+ return false;
+
+ /* make sure psys is in the object */
+ return BLI_findindex(&psmd->ob->particlesystem, psys) >= 0;
+}
+
+static PointerRNA rna_ParticleInstanceModifier_particle_system_get(PointerRNA *ptr)
+{
+ ParticleInstanceModifierData *psmd = ptr->data;
+ ParticleSystem *psys;
+ PointerRNA rptr;
+
+ if (!psmd->ob)
+ return PointerRNA_NULL;
+
+ psys = BLI_findlink(&psmd->ob->particlesystem, psmd->psys - 1);
+ RNA_pointer_create((ID *)psmd->ob, &RNA_ParticleSystem, psys, &rptr);
+ return rptr;
+}
+
+static void rna_ParticleInstanceModifier_particle_system_set(PointerRNA *ptr, const PointerRNA value)
+{
+ ParticleInstanceModifierData *psmd = ptr->data;
+
+ if (!psmd->ob)
+ return;
+
+ psmd->psys = BLI_findindex(&psmd->ob->particlesystem, value.data) + 1;
+ CLAMP_MIN(psmd->psys, 1);
+}
+
#else
static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const char type[])
@@ -2655,6 +2692,12 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
+ static EnumPropertyItem particleinstance_space[] = {
+ {eParticleInstanceSpace_Local, "LOCAL", 0, "Local", "Use offset from the particle object in the instance object"},
+ {eParticleInstanceSpace_World, "WORLD", 0, "World", "Use world space offset in the instance object"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
srna = RNA_def_struct(brna, "ParticleInstanceModifier", "Modifier");
RNA_def_struct_ui_text(srna, "ParticleInstance Modifier", "Particle system instancing modifier");
RNA_def_struct_sdna(srna, "ParticleInstanceModifierData");
@@ -2669,16 +2712,30 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna)
prop = RNA_def_property(srna, "particle_system_index", PROP_INT, PROP_NONE);
RNA_def_property_int_sdna(prop, NULL, "psys");
- RNA_def_property_range(prop, 1, 10);
+ RNA_def_property_range(prop, 1, SHRT_MAX);
RNA_def_property_ui_text(prop, "Particle System Number", "");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "ParticleSystem");
+ RNA_def_property_pointer_funcs(prop, "rna_ParticleInstanceModifier_particle_system_get", "rna_ParticleInstanceModifier_particle_system_set",
+ NULL, "rna_ParticleInstanceModifier_particle_system_poll");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Particle System", "");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "axis");
RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
RNA_def_property_ui_text(prop, "Axis", "Pole axis for rotation");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
+
+ prop = RNA_def_property(srna, "space", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "space");
+ RNA_def_property_enum_items(prop, particleinstance_space);
+ RNA_def_property_ui_text(prop, "Space", "Space to use for copying mesh data");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "use_normal", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", eParticleInstanceFlag_Parents);
RNA_def_property_ui_text(prop, "Normal", "Create instances from normal particles");
@@ -2730,6 +2787,40 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0, 1.0);
RNA_def_property_ui_text(prop, "Random Position", "Randomize position along path");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "rotation", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "rotation");
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_text(prop, "Rotation", "Rotation around path");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "random_rotation", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_float_sdna(prop, NULL, "random_rotation");
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_text(prop, "Random Rotation", "Randomize rotation around path");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "particle_amount", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_text(prop, "Particle Amount", "Amount of particles to use for instancing");
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "particle_offset", PROP_FLOAT, PROP_FACTOR);
+ RNA_def_property_range(prop, 0.0, 1.0);
+ RNA_def_property_ui_text(prop, "Particle Offset", "Relative offset of particles to use for instancing, to avoid overlap of multiple instances");
+ RNA_def_property_float_default(prop, 0.0f);
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "index_layer_name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "index_layer_name");
+ RNA_def_property_ui_text(prop, "Index Layer Name", "Custom data layer name for the index");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ prop = RNA_def_property(srna, "value_layer_name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "value_layer_name");
+ RNA_def_property_ui_text(prop, "Value Layer Name", "Custom data layer name for the randomized value");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
static void rna_def_modifier_explode(BlenderRNA *brna)
diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c
index 106a84d3765..f0b80cda447 100644
--- a/source/blender/modifiers/intern/MOD_particleinstance.c
+++ b/source/blender/modifiers/intern/MOD_particleinstance.c
@@ -40,10 +40,12 @@
#include "BLI_math.h"
#include "BLI_listbase.h"
#include "BLI_rand.h"
+#include "BLI_string.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"
@@ -53,8 +55,6 @@
#include "depsgraph_private.h"
#include "DEG_depsgraph_build.h"
-#include "MOD_modifiertypes.h"
-
static void initData(ModifierData *md)
{
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
@@ -64,7 +64,12 @@ static void initData(ModifierData *md)
pimd->psys = 1;
pimd->position = 1.0f;
pimd->axis = 2;
+ pimd->space = eParticleInstanceSpace_World;
+ pimd->particle_amount = 1.0f;
+ pimd->particle_offset = 0.0f;
+ STRNCPY(pimd->index_layer_name, "");
+ STRNCPY(pimd->value_layer_name, "");
}
static void copyData(ModifierData *md, ModifierData *target)
{
@@ -75,6 +80,21 @@ static void copyData(ModifierData *md, ModifierData *target)
modifier_copyData_generic(md, target);
}
+static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *md)
+{
+ ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
+ CustomDataMask dataMask = 0;
+
+ if (pimd->index_layer_name[0] != '\0' ||
+ pimd->value_layer_name[0] != '\0')
+ {
+ dataMask |= CD_MASK_MLOOPCOL;
+ }
+
+ return dataMask;
+
+}
+
static bool isDisabled(ModifierData *md, int useRenderParams)
{
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
@@ -142,39 +162,59 @@ static void foreachObjectLink(ModifierData *md, Object *ob,
walk(userData, ob, &pimd->ob, IDWALK_CB_NOP);
}
-static int particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
+static bool particle_skip(ParticleInstanceModifierData *pimd, ParticleSystem *psys, int p)
{
+ const bool between = (psys->part->childtype == PART_CHILD_FACES);
ParticleData *pa;
+ int totpart, randp, minp, maxp;
- 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;
- }
+ if (p >= psys->totpart) {
+ ChildParticle *cpa = psys->child + (p - psys->totpart);
+ pa = psys->particles + (between? cpa->pa[0]: cpa->parent);
}
else {
- if (psys->part->childtype == PART_CHILD_PARTICLES) {
- pa = psys->particles + (psys->child + p)->parent;
- }
- else {
- pa = NULL;
- }
+ pa = psys->particles + p;
}
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;
+ if (pa->alive == PARS_UNBORN && (pimd->flag & eParticleInstanceFlag_Unborn) == 0) return true;
+ if (pa->alive == PARS_ALIVE && (pimd->flag & eParticleInstanceFlag_Alive) == 0) return true;
+ if (pa->alive == PARS_DEAD && (pimd->flag & eParticleInstanceFlag_Dead) == 0) return true;
}
- return 0;
+ if (pimd->particle_amount == 1.0f) {
+ /* Early output, all particles are to be instanced. */
+ return false;
+ }
+
+ /* Randomly skip particles based on desired amount of visible particles. */
+
+ totpart = psys->totpart + psys->totchild;
+
+ /* TODO make randomization optional? */
+ randp = (int)(psys_frand(psys, 3578 + p) * totpart) % totpart;
+
+ minp = (int)(totpart * pimd->particle_offset) % (totpart+1);
+ maxp = (int)(totpart * (pimd->particle_offset + pimd->particle_amount)) % (totpart+1);
+
+ if (maxp > minp) {
+ return randp < minp || randp >= maxp;
+ }
+ else if (maxp < minp) {
+ return randp < minp && randp >= maxp;
+ }
+ else {
+ return true;
+ }
+
+ return false;
+}
+
+static void store_float_in_vcol(MLoopCol *vcol, float float_value)
+{
+ const uchar value = FTOCHAR(float_value);
+ vcol->r = vcol->g = vcol->b = value;
+ vcol->a = 1.0f;
}
static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
@@ -190,11 +230,15 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
MLoop *mloop, *orig_mloop;
MVert *mvert, *orig_mvert;
int totvert, totpoly, totloop /* , totedge */;
- int maxvert, maxpoly, maxloop, totpart = 0, first_particle = 0;
+ int maxvert, maxpoly, maxloop, part_end = 0, part_start;
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;
+ float spacemat[4][4];
+ const bool use_parents = pimd->flag & eParticleInstanceFlag_Parents;
+ const bool use_children = pimd->flag & eParticleInstanceFlag_Children;
+ bool between;
trackneg = ((ob->trackflag > 2) ? 1 : 0);
@@ -212,25 +256,26 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
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;
- }
+ part_start = use_parents ? 0 : psys->totpart;
+
+ part_end = 0;
+ if (use_parents)
+ part_end += psys->totpart;
+ if (use_children)
+ part_end += psys->totchild;
- if (totpart == 0)
+ if (part_end == 0)
return derivedData;
sim.scene = md->scene;
sim.ob = pimd->ob;
sim.psys = psys;
sim.psmd = psys_get_modifier(pimd->ob, psys);
+ between = (psys->part->childtype == PART_CHILD_FACES);
if (pimd->flag & eParticleInstanceFlag_UseSize) {
float *si;
- si = size = MEM_calloc_arrayN(totpart, sizeof(float), "particle size array");
+ si = size = MEM_calloc_arrayN(part_end, sizeof(float), "particle size array");
if (pimd->flag & eParticleInstanceFlag_Parents) {
for (p = 0, pa = psys->particles; p < psys->totpart; p++, pa++, si++)
@@ -246,6 +291,21 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
}
+ switch (pimd->space) {
+ case eParticleInstanceSpace_World:
+ /* particle states are in world space already */
+ unit_m4(spacemat);
+ break;
+ case eParticleInstanceSpace_Local:
+ /* get particle states in the particle object's local space */
+ invert_m4_m4(spacemat, pimd->ob->obmat);
+ break;
+ default:
+ /* should not happen */
+ BLI_assert(false);
+ break;
+ }
+
totvert = dm->getNumVerts(dm);
totpoly = dm->getNumPolys(dm);
totloop = dm->getNumLoops(dm);
@@ -256,7 +316,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
maxpoly = 0;
maxloop = 0;
- for (p = 0; p < totpart; p++) {
+ for (p = part_start; p < part_end; p++) {
if (particle_skip(pimd, psys, p))
continue;
@@ -285,9 +345,21 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
mloop = result->getLoopArray(result);
orig_mloop = dm->getLoopArray(dm);
- for (p = 0, p_skip = 0; p < totpart; p++) {
+ MLoopCol *mloopcols_index = CustomData_get_layer_named(&result->loopData, CD_MLOOPCOL, pimd->index_layer_name);
+ MLoopCol *mloopcols_value = CustomData_get_layer_named(&result->loopData, CD_MLOOPCOL, pimd->value_layer_name);
+ int *vert_part_index = NULL;
+ float *vert_part_value = NULL;
+ if (mloopcols_index != NULL) {
+ vert_part_index = MEM_calloc_arrayN(maxvert, sizeof(int), "vertex part index array");
+ }
+ if (mloopcols_value) {
+ vert_part_value = MEM_calloc_arrayN(maxvert, sizeof(float), "vertex part value array");
+ }
+
+ for (p = part_start, p_skip = 0; p < part_end; p++) {
float prev_dir[3];
float frame[4]; /* frame orientation quaternion */
+ float p_random = psys_frand(psys, 77091 + 283*p);
/* skip particle? */
if (particle_skip(pimd, psys, p))
@@ -297,12 +369,20 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
for (k = 0; k < totvert; k++) {
ParticleKey state;
MVert *inMV;
- MVert *mv = mvert + p_skip * totvert + k;
+ int vindex = p_skip * totvert + k;
+ MVert *mv = mvert + vindex;
inMV = orig_mvert + k;
DM_copy_vert_data(dm, result, k, p_skip * totvert + k, 1);
*mv = *inMV;
+ if (vert_part_index != NULL) {
+ vert_part_index[vindex] = p;
+ }
+ if (vert_part_value != NULL) {
+ vert_part_value[vindex] = p_random;
+ }
+
/*change orientation based on object trackflag*/
copy_v3_v3(temp_co, mv->co);
mv->co[axis] = temp_co[track];
@@ -330,7 +410,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
mv->co[axis] = 0.0;
}
- psys_get_particle_on_path(&sim, first_particle + p, &state, 1);
+ psys_get_particle_on_path(&sim, p, &state, 1);
normalize_v3(state.vel);
@@ -339,17 +419,26 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
float hairmat[4][4];
float mat[3][3];
- if (first_particle + p < psys->totpart)
- pa = psys->particles + first_particle + p;
+ if (p < psys->totpart)
+ pa = psys->particles + p;
else {
ChildParticle *cpa = psys->child + (p - psys->totpart);
- pa = psys->particles + cpa->parent;
+ pa = psys->particles + (between? cpa->pa[0]: 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);
+ if (pimd->rotation > 0.0f || pimd->random_rotation > 0.0f) {
+ float angle = 2.0f*M_PI * (pimd->rotation + pimd->random_rotation * (psys_frand(psys, 19957323 + p) - 0.5f));
+ float eul[3] = { 0.0f, 0.0f, angle };
+ float rot[4];
+
+ eul_to_quat(rot, eul);
+ mul_qt_qtqt(frame, frame, rot);
+ }
+
/* note: direction is same as normal vector currently,
* but best to keep this separate so the frame can be
* rotated later if necessary
@@ -386,13 +475,15 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
}
else {
state.time = -1.0;
- psys_get_particle_state(&sim, first_particle + p, &state, 1);
+ psys_get_particle_state(&sim, 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);
+
+ mul_m4_v3(spacemat, mv->co);
}
/* create polys and loops */
@@ -412,6 +503,15 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
DM_copy_loop_data(dm, result, inMP->loopstart, mp->loopstart, j);
for (; j; j--, ml++, inML++) {
ml->v = inML->v + (p_skip * totvert);
+ const int ml_index = (ml - mloop);
+ if (mloopcols_index != NULL) {
+ const int part_index = vert_part_index[ml->v];
+ store_float_in_vcol(&mloopcols_index[ml_index], (float)part_index / psys->totpart);
+ }
+ if (mloopcols_value != NULL) {
+ const float part_value = vert_part_value[ml->v];
+ store_float_in_vcol(&mloopcols_value[ml_index], part_value);
+ }
}
}
}
@@ -429,6 +529,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob,
if (size)
MEM_freeN(size);
+ MEM_SAFE_FREE(vert_part_index);
+ MEM_SAFE_FREE(vert_part_value);
+
result->dirty |= DM_DIRTY_NORMALS;
return result;
@@ -451,7 +554,7 @@ ModifierTypeInfo modifierType_ParticleInstance = {
/* applyModifier */ applyModifier,
/* applyModifierEM */ NULL,
/* initData */ initData,
- /* requiredDataMask */ NULL,
+ /* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepgraph */ updateDepgraph,