Merge branch 'master' into blender2.8

This commit is contained in:
Campbell Barton 2018-04-19 12:53:21 +02:00
commit 9d6a175756
8 changed files with 292 additions and 60 deletions

@ -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")

@ -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;
};

@ -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 {

@ -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;
}
}
}
}
}
}

@ -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 */

@ -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 {

@ -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)

@ -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;
if (totpart == 0)
part_end = 0;
if (use_parents)
part_end += psys->totpart;
if (use_children)
part_end += psys->totchild;
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,