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
path: root/source
diff options
context:
space:
mode:
authorJeroen Bakker <j.bakker@atmind.nl>2018-04-19 15:49:34 +0300
committerJeroen Bakker <j.bakker@atmind.nl>2018-04-19 15:49:34 +0300
commit8a2f0058aeab48e837561719a5dda27985d99ee5 (patch)
treec6ab7e5d849bd08ac44f76e4ac050d6d3002efed /source
parenta305652d87b7d14562e8e22aefe9073f34d2f06e (diff)
parent723c33aba075a6722a73bafe44076982981420ee (diff)
Merge branch 'blender2.8' of git.blender.org:blender into blender2.8
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_icons.h3
-rw-r--r--source/blender/blenkernel/intern/icons.c8
-rw-r--r--source/blender/blenloader/intern/versioning_270.c12
-rw-r--r--source/blender/editors/interface/interface_icons.c10
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c10
-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
8 files changed, 282 insertions, 58 deletions
diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h
index c3f5d7bf7c2..686dba21283 100644
--- a/source/blender/blenkernel/BKE_icons.h
+++ b/source/blender/blenkernel/BKE_icons.h
@@ -39,7 +39,8 @@ typedef void (*DrawInfoFreeFP)(void *drawinfo);
struct Icon {
void *drawinfo;
void *obj;
- short type;
+ /** #ID_Type or 0 when not used for ID preview. */
+ short id_type;
DrawInfoFreeFP drawinfo_free;
};
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index 25a3675896b..7cf7bb7452a 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -477,7 +477,7 @@ void BKE_icon_changed(const int icon_id)
if (icon) {
/* We *only* expect ID-tied icons here, not non-ID icon/preview! */
- BLI_assert(icon->type != 0);
+ BLI_assert(icon->id_type != 0);
/* Do not enforce creation of previews for valid ID types using BKE_previewimg_id_ensure() here ,
* we only want to ensure *existing* preview images are properly tagged as changed/invalid, that's all. */
@@ -503,7 +503,7 @@ static int icon_id_ensure_create_icon(struct ID *id)
new_icon = MEM_mallocN(sizeof(Icon), __func__);
new_icon->obj = id;
- new_icon->type = GS(id->name);
+ new_icon->id_type = GS(id->name);
/* next two lines make sure image gets created */
new_icon->drawinfo = NULL;
@@ -579,7 +579,7 @@ int BKE_icon_preview_ensure(ID *id, PreviewImage *preview)
new_icon = MEM_mallocN(sizeof(Icon), __func__);
new_icon->obj = preview;
- new_icon->type = 0; /* Special, tags as non-ID icon/preview. */
+ new_icon->id_type = 0; /* Special, tags as non-ID icon/preview. */
/* next two lines make sure image gets created */
new_icon->drawinfo = NULL;
@@ -656,7 +656,7 @@ void BKE_icon_delete(const int icon_id)
icon = BLI_ghash_popkey(gIcons, SET_INT_IN_POINTER(icon_id), NULL);
if (icon) {
- if (icon->type) {
+ if (icon->id_type != 0) {
((ID *)(icon->obj))->icon_id = 0;
}
else {
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index e72ed9a41fd..7097fe656b6 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -1787,6 +1787,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/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index b945965ce6a..a33dcfc5ab6 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -143,7 +143,7 @@ static DrawInfo *def_internal_icon(ImBuf *bbuf, int icon_id, int xofs, int yofs,
new_icon = MEM_callocN(sizeof(Icon), "texicon");
new_icon->obj = NULL; /* icon is not for library object */
- new_icon->type = 0;
+ new_icon->id_type = 0;
di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
di->type = type;
@@ -195,7 +195,7 @@ static void def_internal_vicon(int icon_id, VectorDrawFunc drawFunc)
new_icon = MEM_callocN(sizeof(Icon), "texicon");
new_icon->obj = NULL; /* icon is not for library object */
- new_icon->type = 0;
+ new_icon->id_type = 0;
di = MEM_callocN(sizeof(DrawInfo), "drawinfo");
di->type = ICON_TYPE_VECTOR;
@@ -874,7 +874,7 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi
switch (di->type) {
case ICON_TYPE_PREVIEW:
{
- ID *id = (icon->type != 0) ? icon->obj : NULL;
+ ID *id = (icon->id_type != 0) ? icon->obj : NULL;
PreviewImage *prv = id ? BKE_previewimg_id_ensure(id) : icon->obj;
/* Using jobs for screen previews crashes due to offscreen rendering.
* XXX would be nicer if PreviewImage could store if it supports jobs */
@@ -933,7 +933,7 @@ PreviewImage *UI_icon_to_preview(int icon_id)
DrawInfo *di = (DrawInfo *)icon->drawinfo;
if (di) {
if (di->type == ICON_TYPE_PREVIEW) {
- PreviewImage *prv = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
+ PreviewImage *prv = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
if (prv) {
return BKE_previewimg_copy(prv);
@@ -1237,7 +1237,7 @@ static void icon_draw_size(
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
}
else if (di->type == ICON_TYPE_PREVIEW) {
- PreviewImage *pi = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
+ PreviewImage *pi = (icon->id_type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj;
if (pi) {
/* no create icon on this level in code */
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index b9a4a883b63..20f05502b35 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -719,7 +719,7 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR);
- immBegin(GWN_PRIM_TRIS, tri_count * 3);
+ Gwn_Batch *face_batch = immBeginBatch(GWN_PRIM_TRIS, tri_count * 3);
for (unsigned int i = 0; i < em->tottri; i++) {
efa = em->looptris[i][0]->f;
if (BM_elem_flag_test(efa, BM_ELEM_TAG)) {
@@ -740,6 +740,11 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
}
immEnd();
+ /* XXX performance: we should not create and throw away result. */
+ GWN_batch_draw(face_batch);
+ GWN_batch_program_use_end(face_batch);
+ GWN_batch_discard(face_batch);
+
immUnbindProgram();
glDisable(GL_BLEND);
@@ -931,6 +936,9 @@ static void draw_uvs(SpaceImage *sima, Scene *scene, ViewLayer *view_layer, Obje
GWN_vertbuf_discard(uv_vbo);
GWN_batch_discard(uv_batch);
}
+ else {
+ immUnbindProgram();
+ }
if (sima->flag & SI_SMOOTH_UV) {
glDisable(GL_LINE_SMOOTH);
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h
index 283e801ea7a..64e6ce3d522 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 99417ee7b1b..86f69606bb1 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1157,6 +1157,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[])
@@ -2652,6 +2689,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");
@@ -2666,16 +2709,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");
@@ -2727,6 +2784,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 99433ae3725..d7cb7fd8d94 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"
@@ -52,8 +54,6 @@
#include "DEG_depsgraph_build.h"
-#include "MOD_modifiertypes.h"
-
static void initData(ModifierData *md)
{
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *) md;
@@ -63,7 +63,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)
{
@@ -74,6 +79,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;
@@ -127,39 +147,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, struct Depsgraph *depsgraph,
@@ -175,11 +215,15 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
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);
@@ -197,15 +241,15 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
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.depsgraph = depsgraph;
@@ -213,10 +257,11 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
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++)
@@ -232,6 +277,21 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
}
}
+ 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);
@@ -242,7 +302,7 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
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;
@@ -271,9 +331,21 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
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))
@@ -283,12 +355,20 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
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];
@@ -316,7 +396,7 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
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);
@@ -325,17 +405,26 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
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
@@ -372,13 +461,15 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
}
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 */
@@ -398,6 +489,15 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
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);
+ }
}
}
}
@@ -415,6 +515,9 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Depsgraph *depsgraph,
if (size)
MEM_freeN(size);
+ MEM_SAFE_FREE(vert_part_index);
+ MEM_SAFE_FREE(vert_part_value);
+
result->dirty |= DM_DIRTY_NORMALS;
return result;
@@ -437,7 +540,7 @@ ModifierTypeInfo modifierType_ParticleInstance = {
/* applyModifier */ applyModifier,
/* applyModifierEM */ NULL,
/* initData */ initData,
- /* requiredDataMask */ NULL,
+ /* requiredDataMask */ requiredDataMask,
/* freeData */ NULL,
/* isDisabled */ isDisabled,
/* updateDepsgraph */ updateDepsgraph,